You can compile a simple lambda expression to get your delegate.
var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();
Question
I have a type that is created at runtime (through compilation from CodeDOM) and implements a known (at compile time) interface.
Suppose the interface is IMyInterface
, and I have the Type instance Type myType
that I acquired from the assembly I just compiled from the CodeDOM. The class that myType
represents implements IMyInterface
.
I would like to get a delegate Func<IMyInterface>
that, when Invoked, will return an instance of myType
.
Something I would like to call in this way:
Func<IMyInterface> createObject = GetObjectCreator<IMyInterface>(myType);
IMyInterface myObject = createObject();
I know that if I have a MethodInfo m
for a parameterless method that returns an instance of myType object, then I could do something like this:
Func<IMyInterface> createObject =
( Func<IMyInterface> )Delegate.CreateDelegate(typeof(Func<IMyInterface>), m);
But if I don't have such a method, and the only thing I have is the type's parameterless constructor, then how do I get this delegate?
Though fsimonazzi's answer did exactly what I was asking for, my approach was a bit different.
Since I control the creation and compilation of the myType
Type, I added a public static method that returns an instance of that type. Then, after compiling this type, I got a MethodInfo instance for this method, and created the desired delegate calling 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);
The above code generates this code and puts in into the class declaration
public static MyNamespace.MyClass __Instantiator()
{
return new MyNamespace.MyClass();
}
Now compiling this code and having a myType
Type instance for this class, I can do
Func<IMyInterface> createObject = ( Func<IMyInterface> )(
Delegate.CreateDelegate(typeof(Func<IMyInterface>),
myType.GetMethod("__Instantiator")) );
IMyInterface obj = createObject(); // This will call MyClass.__Instantiator()
Solution
You can compile a simple lambda expression to get your delegate.
var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();
OTHER TIPS
You can use Activator.CreateInstance( type )
to actually create an instance of your type. If you want this stuffed in a Func<IMyInterface>
then you can just wrap it in a lambda:
Func<IMyInterface> createObject = () => (IMyInterface) Activator.CreateInstance( myType );
IMyInterface myObject = createObject();
UPDATE:
Since Activator.CreateInstance
is evidently not what you're looking for (though I'm not entirely sure why), I suppose you could use reflection to find the parameterless constructor of the type:
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 );
}