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

使用Activator或任何返回的答案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 回答