2

私たちが知っているように、コンストラクターは次のFunc<T>ように指定できます。

Func<MyObject> constructor = () => new MyObject();
var newObject = constructor();

しかし、 MyObject から継承されていることがわかっているが、その正確な型がわからないオブジェクトのコンストラクターを作成する方法はありますか?

Type inheritedObjectType = obj; // Parameter
Func<MyObject> constructor = () => new MyObject(); // as inheritedObjectType
var newInheritedObject = constructor; // Should now be of the inherited type

Activatorusingまたは何かを返すという答えObjectはオプションではありません。

編集:コンパイル時に派生型がどの型かわかりません。私はSystem.Type.

4

2 に答える 2

6

式ツリーを使用して、派生型を作成するデリゲートを構築およびコンパイルできます。

Func<TBase> CreateDelegate<TBase>(Type derived)
{
    var ctor = derived.GetConstructor(Type.EmptyTypes);

    if (ctor == null)
    {
        throw new ArgumentException("D'oh! No default ctor.");
    }

    var newExpression = Expression.Lambda<Func<TBase>>(
        Expression.New(ctor, new Expression[0]), 
        new ParameterExpression[0]);

    return newExpression.Compile();
}

次のように簡単に呼び出すことができます。

Func<MyBase> create = CreateDelegate<MyBase>(typeof(Derived));

MyBase instance = create();

そのデリゲートをキャッシュすると、最大のパフォーマンスが得られます。

于 2011-05-30T14:20:43.700 に答える
2

このプログラムは目的の動作を示していますか?

class MyObject{}
class Derived : MyObject {}
internal class Program
{

    public static void Main()
    {
        // the type you want to construct
        Type type = typeof (Derived);

        MethodInfo getConstructor = MakeConstructorGetter(type);
        Func<MyObject> constructor = (Func<MyObject>)getConstructor.Invoke(null, null);

        var obj = constructor();
        Console.WriteLine(obj.GetType());
    }

    private static MethodInfo MakeConstructorGetter(Type type)
    {
        MethodInfo mi = typeof(Program).GetMethod("GetObjectConstructor", BindingFlags.Static | BindingFlags.NonPublic);
        var getConstructor = mi.MakeGenericMethod(type);
        return getConstructor;
    }

    private static Func<T> GetObjectConstructor<T>() where T : MyObject, new()
    {
        return () => new T();
    }
}

MakeConstructorGetterTypeで記述された型が一般的な制約と一致しない場合、例外がスローされます。したがって、これはコンパイル時ではなく実行時に失敗しますが、このようにジェネリックを動的に処理する場合はトレードオフが必要になると思います。

于 2011-05-30T14:05:19.537 に答える