2012-05-15 3 views
4

с помощью отражения, я пытаюсь создать делегат из конструкторы без параметров, как это:Создание делегата из конструктора

Delegate del = GetMethodInfo(() => System.Activator.CreateInstance(type)).CreateDelegate(delType); 

static MethodInfo GetMethodInfo(Expression<Func<object>> func) 
{ 
    return ((MethodCallExpression)func.Body).Method; 
} 

Но я получаю это исключение: «Невозможно привязать к целевому методу, потому что его подпись или прозрачность безопасности несовместима с прозрачностью типа делегата ». Что будет работать?

Отметьте, что CreateDelegate был перемещен, для этого профиля, по крайней мере, с предыдущей версии .NET. Теперь это на MethodInfo.

+0

Вы пытаетесь создать делегат, который вызывает конструктор без параметров тип, в котором у вас есть экземпляр типа? –

+0

Вы правы, Питер. – HappyNomad

ответ

7

Как phoog указывает конструктор не "возврата" значение; плюс вы получите информацию об этом с ConstructorInfo, а не MethodInfo; что означает, что вы не можете создать делегат вокруг него напрямую. Вы должны создать код, который вызывает конструктор и возвращает значение. Например:

var ctor = type.GetConstructor(Type.EmptyTypes); 
if (ctor == null) throw new MissingMethodException("There is no constructor without defined parameters for this object"); 
DynamicMethod dynamic = new DynamicMethod(string.Empty, 
      type, 
      Type.EmptyTypes, 
      type); 
ILGenerator il = dynamic.GetILGenerator(); 

il.DeclareLocal(type); 
il.Emit(OpCodes.Newobj, ctor); 
il.Emit(OpCodes.Stloc_0); 
il.Emit(OpCodes.Ldloc_0); 
il.Emit(OpCodes.Ret); 

var func = (Func<object>)dynamic.CreateDelegate(typeof(Func<object>)); 

Конечно, если вы не знаете тип во время компиляции, то вы можете иметь дело только с Object ...

+0

Мой код работает именно так. Благодаря! Можете ли вы также объяснить, почему ваш подход работает, но у меня нет? Я также пытался «создать делегата вокруг» конструктора. – HappyNomad

2

Было бы не очень полезно иметь делегата, который указывает на конструктор, поскольку конструкторы не имеют возвращаемого значения. Делегат построил объект, но не предоставил вам никакой ссылки на него.

Вы, конечно, можете создать делегат, которые возвращают вновь построенный объект:

Func<object> theDelegate =() => new object(); 

Вы также можете создать делегат из Invoke() метода конструктора ConstructorInfo

Для других типов объектов:

Func<string> theDelegate =() => new string('w', 3); 
Func<SomeClassInMyProject> theDelegate =() => new SomeClassInMyProject(); 

Последняя строка предполагает наличие доступного конструктора без параметров.

Обновление с CreateDelegate()

T CallConstructor<T>() where T : new() { return new T(); } 
Delegate MakeTheDelegate(Type t) 
{ 
    MethodInfo generic = //use your favorite technique to get the MethodInfo for the CallConstructor method 
    MethodInfo constructed = generic.MakeGenericMethod(t); 
    Type delType = typeof(Func<>).MakeGenericType(t); 
    return constructed.CreateDelegate(delType); 
} 
+0

Мне нужен делегат, тип которого точно соответствует delType, который возвращает созданный объект. Этот код не помогает, так как результат имеет тип Func , а не delType. – HappyNomad

+0

@HappyНогда код возвращает точный тип созданного объекта, так как объект создается с помощью оператора 'new object()'. Я добавил несколько примеров того, как это сделать с другими типами. – phoog

+0

@HappyNomad в ответ на ваш комментарий: если вы не знаете тип объекта во время выполнения, зачем нужен строго типизированный делегат? – phoog