3

仲間のメンバーに挨拶します。問題の状況は次のとおりです。

public abstract class BaseClass
{
    protected BaseClass()
    {
        // some logic here
    }

    protected BaseClass(Object parameter) : this()
    {
        // some more logic
    }
}

public class Descendant : BaseClass
{
   // no constructors
}

Descendant クラスでActivator.CreateInstanceを呼び出そうとしていますが、コンストラクターが見つかりません。

Descentant クラスで明示的に定義する必要がありますか?

私が使用したバインディングは次のとおりです。BindingFlags.Instance | BindingFlags.NonPublic

注 1 : 何らかの影響があれば、実際には AppDomain.CreateInstanceAndUnwrap() を呼び出しています。

 domain.CreateInstanceAndUnwrap(path, typeName, false, BindingFlags.Instance |
     BindingFlags.NonPublic, null, new[] { parameter }, null, null);

注 2 : Descendant クラスで保護されたコンストラクターを明示的に定義すると機能しますが、可能であればこれを避けたいと思います。

4

2 に答える 2

4

Activator.CreateInstance は使用できませんが、完全信頼環境では、リフレクションによって直接コンストラクターを見つけて呼び出すことができるはずです。

実際、Descendant クラスは、基本クラスの保護されたコンストラクターへのパススルーを行うパブリック コンストラクターを自動的に提供します。これはうまくいくはずです:

Activator.CreateInstance(typeof(Descendant))

さて、デフォルト以外のコンストラクターを呼び出そうとしていることに気付きました。残念ながら、これは許可されていません。基本クラスは抽象であるため、基本クラスでコンストラクターを直接呼び出すことはできません。オブジェクトを構築するには、子孫クラスにコンストラクター (自動生成または明示的に定義) が必要です。

Descendant クラスでパススルー コンストラクターを作成することもできますが、あなたのコメントは、実装者がコンストラクターで値を渡すことを強制することを避けようとしているように聞こえます。おそらく本当に必要なのは、オブジェクトの構築後に呼び出すことができる初期化メソッドです。

// Define other methods and classes here
public abstract class BaseClass
{
    protected BaseClass()
    {
        // some logic here
    }

    protected Object Parameter {get; private set;}    

    public virtual void Initialize(Object parameter)
    {
        Parameter = _parameter;
        // some more logic
    }
}
于 2012-04-10T22:33:00.700 に答える
1

ここで必要なのは、コンストラクターではなくビルダー パターンです。それは非常に簡単です。必要なクラスを「構築」するクラスを (デフォルトのコンストラクターで) 定義します。このようなもの(注:未テストのコード先):

public abstract class BaseBuildable : MarshalByRefObject {
   public String Foo { get; internal set; }
}

public class DerivedBuildable : BaseBuildable { }

public class BuildableBuilder : MarshalByRefObject {
   private String _foo;
   public BuildableBuilder WithFoo(String foo) { _foo = foo; return this; }
   public TBuildable Build<TBuildable>() where TBuildable : BaseBuildable, new() {
       return new TBuildable { Foo = _foo; }
   }
}

// Used so:
var builder = domain.CreateInstanceAndUnwrap(.. // yadda yadda, you want a BuildableBuilder
var buildable = builder.WithFoo("Foo, yo").Build();
于 2012-04-10T23:03:24.643 に答える