Вы можете собрать простое выражение Lambda, чтобы получить свой делегат.
var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();
Вопрос
У меня есть тип, который создается во время выполнения (посредством компиляции из Codedom) и реализует известный (при компиляции) интерфейс.
Предположим, что интерфейс IMyInterface
, и у меня есть экземпляр типа Type myType
Что я приобрел из сборки, которую я только что собрал из кодирования. Класс, что myType
представляет орудия IMyInterface
.
Я хотел бы получить делегата Func<IMyInterface>
что, когда вы приведут myType
.
Что -то, что я хотел бы позвонить таким образом:
Func<IMyInterface> createObject = GetObjectCreator<IMyInterface>(myType);
IMyInterface myObject = createObject();
Я знаю, что если у меня есть MethodInfo m
Для метода без параметра, который возвращает экземпляр объекта Mytype, тогда я мог бы сделать что -то подобное:
Func<IMyInterface> createObject =
( Func<IMyInterface> )Delegate.CreateDelegate(typeof(Func<IMyInterface>), m);
Но если у меня нет такого метода, и единственное, что у меня есть, это конструктор без параметра, то как мне получить этот делегат?
Хотя ответ Fsimonazzi сделал именно то, о чем я просил, мой подход был немного другим.
Поскольку я контролирую создание и сборник myType
Тип, я добавил общественный статический метод, который возвращает экземпляр такого типа. Затем, после составления этого типа, я получил экземпляр MethodInfo для этого метода и создал желаемый делегат Callgate.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
Тип экземпляра для этого класса, я могу сделать
Func<IMyInterface> createObject = ( Func<IMyInterface> )(
Delegate.CreateDelegate(typeof(Func<IMyInterface>),
myType.GetMethod("__Instantiator")) );
IMyInterface obj = createObject(); // This will call MyClass.__Instantiator()
Решение
Вы можете собрать простое выражение Lambda, чтобы получить свой делегат.
var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();
Другие советы
Вы можете использовать Activator.CreateInstance( type )
Чтобы фактически создать экземпляр вашего типа. Если вы хотите набиться в Func<IMyInterface>
Тогда вы можете просто обернуть его в лямбду:
Func<IMyInterface> createObject = () => (IMyInterface) Activator.CreateInstance( myType );
IMyInterface myObject = createObject();
ОБНОВИТЬ:
С Activator.CreateInstance
Очевидно, не то, что вы ищете (хотя я не совсем уверен, почему), я полагаю, вы могли бы использовать отражение, чтобы найти конструктор без параметра типа:
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 );
}