C# 从实现已知接口的未知类型构造函数创建委托

C# 从实现已知接口的未知类型构造函数创建委托,c#,dynamic,reflection,code-generation,codedom,C#,Dynamic,Reflection,Code Generation,Codedom,我有一个在运行时(通过从CodeDOM编译)创建的类型,并实现一个已知(在编译时)接口 假设接口是IMyInterface,我有一个类型实例Type myType,它是我从刚刚从CodeDOM编译的程序集中获取的。myType表示的类实现了IMyInterface 我想获取一个委托Func,调用该委托时,它将返回myType的实例 我想用这种方式称之为: Func<IMyInterface> createObject = GetObjectCreator<IMyInterfac

我有一个在运行时(通过从CodeDOM编译)创建的类型,并实现一个已知(在编译时)接口

假设接口是
IMyInterface
,我有一个类型实例
Type myType
,它是我从刚刚从CodeDOM编译的程序集中获取的。
myType
表示的类实现了
IMyInterface

我想获取一个委托
Func
,调用该委托时,它将返回
myType
的实例

我想用这种方式称之为:

Func<IMyInterface> createObject = GetObjectCreator<IMyInterface>(myType);
IMyInterface myObject = createObject();
但是如果我没有这样的方法,而我唯一拥有的就是类型的无参数构造函数,那么我如何获得这个委托呢

更新 虽然费西蒙纳齐的回答完全符合我的要求,但我的方法有点不同

由于我控制
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
Type实例,我可以

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

IMyInterface obj = createObject(); // This will call MyClass.__Instantiator()
Func createObject=(Func)(
Delegate.CreateDelegate(typeof(Func),
GetMethod(“实例化器”);
IMyInterface obj=createObject();//这将调用MyClass.\uu实例化器()

您可以使用
Activator.CreateInstance(type)
实际创建您的类型的实例。如果您想将其填充在
Func
中,则可以将其包装在lambda中:

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

可以编译一个简单的lambda表达式来获取委托

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

您忘记了实际创建对象,请调用Activator.CreateInstance()。关键是不要使用此技术。GetObjectCreator应该为将为我创建实例的方法返回委托。如果有必要,可以在运行时编译该方法,但我不想每次需要实例时都调用Activator.CreateInstance()。您最好考虑一下。单身是一个名字很漂亮的虫子。谁说单身?我只会得到一个委托,我可以调用它一百万次,得到一百万个“myType”实例,你不明白我要的是什么。方法“IMyInterface Create(){return new myType();}”只是一个方法,但每次调用它时都返回一个新实例。整个问题是我没有这个方法,而且我在编译时不知道“myType”,所以我想在运行时创建它。看看fsimonazzi的答案。这两种方法都在创建实例时使用反射,这不是我想要的。我不想要它的原因是反射应该比构造函数的实际调用“new t()”慢,不是吗?因此,我想动态获取/创建/编译调用“new T()”(而不是ctor.Invoke)并返回它的函数。然后,我将委派一名代表执行此函数。因此,最终,调用委托将执行“new T()”而不是任何其他反射方式。您是否实际分析了这些解决方案的性能?如果不是,你只是过早地进行微观优化。如果这是您真正想要的,我会使用@fsimonazzi给出的解决方案。这在调用委托时不涉及任何反射,对吗?此外,这行代码是否编译并在内存中加载其他程序集?编译委托后不涉及任何反射。该方法被添加到所有动态方法共享的临时程序集(“匿名托管的DynamicMethods程序集”)。
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 );
}
var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();