2012-05-15 63 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

你們是不是要創建可調用的參數的構造函數的委託一個只有Type實例的類型? –

+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(); 

你也可以從構造的ConstructorInfo

對於其他類型的對象Invoke()方法創建一個委託:

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

@HappyNomad代碼確實會返回創建對象的確切類型,因爲該對象是使用語句'new object()'創建的。我已經添加了一些如何與其他類型一起使用的示例。 – phoog

+0

@HappyNomad迴應你的評論:如果你不知道運行時的對象類型,爲什麼你需要一個強類型的代表? – phoog