既知のインターフェイスを実装する未知のタイプのコンストラクターからデリゲートを作成する

StackOverflow https://stackoverflow.com/questions/20353277

質問

実行時に(Codedomからのコンピレーションを通じて)作成され、既知の(コンパイル時間)インターフェイスを実装するタイプがあります。

インターフェイスがあると仮定します IMyInterface, 、そして、私はタイプインスタンスを持っています Type myType 私がコーディングから編集したばかりのアセンブリから取得したこと。クラス myType 実装を表します IMyInterface.

代表者をもらいたいのですが Func<IMyInterface> それは、呼び出されたときに、のインスタンスを返します myType.

このように呼びたいもの:

Func<IMyInterface> createObject = GetObjectCreator<IMyInterface>(myType);
IMyInterface myObject = createObject();

私が持っている場合、私はそれを知っています MethodInfo m myTypeオブジェクトのインスタンスを返すパラメーターのないメソッドの場合、次のようなことを行うことができます。

Func<IMyInterface> createObject =
  ( Func<IMyInterface> )Delegate.CreateDelegate(typeof(Func<IMyInterface>), m);

しかし、私がそのような方法を持っていない場合、そして私が持っている唯一のものがタイプのパラメーターレスコンストラクターだけである場合、この代表者を取得するにはどうすればよいですか?

アップデート

Fsimonazziの答えは私が求めていたことを正確に行いましたが、私のアプローチは少し違っていました。

私はの作成と編集を制御しているので myType タイプ、そのタイプのインスタンスを返すパブリック静的メソッドを追加しました。次に、このタイプをコンパイルした後、この方法のMethodInfoインスタンスを取得し、Delegate.createdElegateを呼び出す目的のデリゲートを作成しました。

CodeTypeDeclaration type = new CodeTypeDeclaration
{
    Name = "MyClass",
    IsClass = true,
    TypeAttributes = TypeAttributes.Public
};

type.BaseTypes.Add(new CodeTypeReference(typeof(IMyInterface)));

// fullName is the full name of the myType (including namespace)
var staticInstantiator = new CodeMemberMethod
{
    Name = "__Instantiator",
    ReturnType = new CodeTypeReference("MyNamespace.MyClass"),
    Attributes = MemberAttributes.Public | MemberAttributes.Static
};

staticInstantiator.Statements.Add(
   new CodeMethodReturnStatement(
       new CodeObjectCreateExpression("MyNamespace.MyClass")));

    type.Members.Add(staticInstantiator);

上記のコードはこのコードを生成し、クラス宣言に入れます

public static MyNamespace.MyClass __Instantiator()
{
    return new MyNamespace.MyClass();
}

このコードをコンパイルして、 myType このクラスのインスタンスと入力してください

Func<IMyInterface> createObject = ( Func<IMyInterface> )(
    Delegate.CreateDelegate(typeof(Func<IMyInterface>),
                            myType.GetMethod("__Instantiator")) );

IMyInterface obj = createObject(); // This will call MyClass.__Instantiator()
役に立ちましたか?

解決

シンプルなラムダ式をコンパイルして、デリゲートを取得できます。

var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();

他のヒント

使用できます Activator.CreateInstance( type ) 実際にあなたのタイプのインスタンスを作成します。これを詰めたい場合 Func<IMyInterface> それからあなたはそれをラムダで包むことができます:

Func<IMyInterface> createObject = () => (IMyInterface) Activator.CreateInstance( myType );
IMyInterface myObject = createObject();

アップデート:

以来 Activator.CreateInstance 明らかにあなたが探しているものではありません(私は完全にはわかりませんが)、私はあなたが反射を使用してタイプのパラメーターのないコンストラクターを見つけることができると思います:

public Func<T> GetObjectCreator<T>( Type type )
{
    // I'd probably add additional checks here to see that the
    // conversion to T is actually possible.

    var ctor = type.GetConstructor( Type.EmptyTypes );

    if( ctor == null ) throw new ArgumentException( "type", "Public parameterless constructor not found." )

    return () => (T) ctor.Invoke( null );
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top