Sie können einen einfachen Lambda -Ausdruck zusammenstellen, um Ihren Delegierten zu erhalten.
var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();
Frage
Ich habe einen Typ, der zur Laufzeit erstellt wird (durch Zusammenstellung von CodedOM) und eine bekannte (zur Kompilierzeit) Schnittstelle implementiert.
Angenommen, die Schnittstelle ist IMyInterface
, und ich habe die Typinstanz Type myType
Dass ich von der Baugruppe erworben habe, habe ich gerade aus dem Codedom zusammengestellt. Die Klasse das myType
repräsentiert Geräte IMyInterface
.
Ich möchte einen Delegierten bekommen Func<IMyInterface>
Das wird beim Aufrufen eine Instanz von zurückgegeben myType
.
Etwas, das ich auf diese Weise anrufen möchte:
Func<IMyInterface> createObject = GetObjectCreator<IMyInterface>(myType);
IMyInterface myObject = createObject();
Ich weiß das, wenn ich eine habe MethodInfo m
Für eine parameterlose Methode, die eine Instanz des MyType -Objekts zurückgibt, könnte ich so etwas tun:
Func<IMyInterface> createObject =
( Func<IMyInterface> )Delegate.CreateDelegate(typeof(Func<IMyInterface>), m);
Aber wenn ich keine solche Methode habe und das einzige, was ich habe, ist der parameterlose Konstruktor des Typs, wie bekomme ich dann diesen Delegierten?
Obwohl Fsimonazzis Antwort genau das tat, was ich verlangte, war mein Ansatz etwas anders.
Da ich die Schöpfung und Zusammenstellung der kontrolliere myType
Typ, ich habe eine öffentliche statische Methode hinzugefügt, die eine Instanz dieser Art zurückgibt. Nachdem ich diesen Typ zusammengestellt hatte, erhielt ich eine MethodeInfo -Instanz für diese Methode und erstellte den gewünschten Delegierten -Aufruf -Delegaten. 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);
Der obige Code generiert diesen Code und stellt die Klassenerklärung ein
public static MyNamespace.MyClass __Instantiator()
{
return new MyNamespace.MyClass();
}
Jetzt kompilieren Sie diesen Code und haben Sie eine myType
Geben Sie eine Instanz für diese Klasse ein, ich kann es tun
Func<IMyInterface> createObject = ( Func<IMyInterface> )(
Delegate.CreateDelegate(typeof(Func<IMyInterface>),
myType.GetMethod("__Instantiator")) );
IMyInterface obj = createObject(); // This will call MyClass.__Instantiator()
Lösung
Sie können einen einfachen Lambda -Ausdruck zusammenstellen, um Ihren Delegierten zu erhalten.
var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();
Andere Tipps
Sie können verwenden Activator.CreateInstance( type )
Um tatsächlich eine Instanz Ihres Typs zu erstellen. Wenn Sie dies in einem ausgestopft haben möchten Func<IMyInterface>
Dann können Sie es einfach in eine Lambda einwickeln:
Func<IMyInterface> createObject = () => (IMyInterface) Activator.CreateInstance( myType );
IMyInterface myObject = createObject();
AKTUALISIEREN:
Seit Activator.CreateInstance
ist offensichtlich nicht das, wonach Sie suchen (obwohl ich mir nicht ganz sicher bin, warum), können Sie nach Überlegungen verwenden, um den parameterlosen Konstruktor des Typs zu finden:
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 );
}