2012-04-10 5 views
3

挨拶仲間のメンバーは、:保護されたコンストラクタを持つオブジェクトのインスタンスを作成することは可能ですか?問題の状況は、このようなある

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

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

public class Descendant : BaseClass 
{ 
    // no constructors 
} 

私は子孫クラスに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:私は明示的に子孫クラスで保護されたコンストラクタを定義する場合、それは動作しますが、私は、可能な場合は、これを避けるためにしたいと思います。

+0

問題はコンストラクタが実際に継承されていないため、派生型を検索することが非生産的であることです。 – dlev

+0

私はそれを知っていますが、他のプログラマーにその1つのデフォルトコンストラクターを何度も強制的に実装させたくありません(私はそれも嫌いです)。 – SmartK8

+0

それを知っていれば、別のアプローチが必要であることもわかります。呼び出すコンストラクタが存在しません! – dlev

答えて

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 
    } 
} 
+0

しかし、それはAppDomain内で達成することができます、どういうわけかコンストラクタをアンラップし、それを呼び出すことができますか? – SmartK8

+0

実際にはそうではありません。 'CreateInstance'は、保護されたコンストラクタを特に探すことになります。ここでの問題は、派生クラスが実際に*保護されているかそうでないかのようなコンストラクタを持っていないことです。 – dlev

+0

私の答えを更新しました。この場合、子孫クラスにはデフォルトのpublicコンストラクターがあります。 – StriplingWarrior

1

あなたはここにしたいようにそれはそう何Builderパターンではなく、コンストラクタよりも、です。これは非常に簡単です。必要なクラスを "ビルド"するクラス(デフォルトのコンストラクタを使用して)を定義します。このようなもの(注:テストされていないコードが先です):

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(); 
+0

でも、DerivedBuildableにはまだ保護されているコンストラクタがあることがわかりますか? (私は実際に取り除こうとしています) – SmartK8

+0

正しく更新されました。コンストラクタはパラメータなしで、既定のコンストラクタを使用していたことを示しています。 –

+0

これは合理的です。私はあなたに投票し、StriplingWarriorに答えを残します。私は眠そうです(ヨーロッパ)、私は明日この問題を解決します。 – SmartK8

関連する問題