由於喬恩斯基特在this問題的答案,我有以下工作:的MethodInfo,createDelegate方法和泛型方法
public delegate BaseItem GetItemDelegate(Guid itemID);
public static class Lists
{
public static GetItemDelegate GetItemDelegateForType(Type derivedType)
{
MethodInfo method = typeof(Lists).GetMethod("GetItem");
method = method.MakeGenericMethod(new Type[] { derivedType });
return (GetItemDelegate)Delegate.CreateDelegate(typeof(GetItemDelegate), method);
}
public static T GetItem<T>(Guid itemID) where T : class { // returns an item of type T ... }
}
public class DerivedItem : BaseItem { }
// I can call it like so:
GetItemDelegate getItem = Lists.GetItemDelegateForType(typeof(DerivedItem));
DerivedItem myItem = getItem(someID); // this works great
當我嘗試運用同樣的事情的方法具有不同的返回類型和過載(那些是我能想出的唯一區別),我得到一個惱人的「ArgumentException:錯誤綁定到目標方法。」致電CreateDelegate
。以下是一個可以獲取錯誤的實例,只需複製/粘貼到控制檯應用程序中。
public delegate IEnumerable<BaseItem> GetListDelegate();
public class BaseItem { }
public class DerivedItem : BaseItem { }
public static class Lists
{
public static GetListDelegate GetListDelegateForType(Type itemType)
{
MethodInfo method = typeof(Lists).GetMethod("GetList", Type.EmptyTypes); // get the overload with no parameters
method = method.MakeGenericMethod(new Type[] { itemType });
return (GetListDelegate)Delegate.CreateDelegate(typeof(GetListDelegate), method);
}
// this is the one I want a delegate to, hence the Type.EmptyTypes above
public static IEnumerable<T> GetList<T>() where T : class { return new List<T>(0); }
// not the one I want a delegate to; included for illustration
public static IEnumerable<T> GetList<T>(int param) where T : class { return new List<T>(0); }
public static Type GetItemType()
{ // this could return any type derived from BaseItem
return typeof(DerivedItem);
}
}
class Program
{
static void Main(string[] args)
{
Type itemType = Lists.GetItemType();
GetListDelegate getList = Lists.GetListDelegateForType(itemType);
IEnumerable<BaseItem> myList = (IEnumerable<BaseItem>)getList();
}
}
正如上面提到的,我能看到的唯一區別是:
- 不同的返回類型(
T
作品,IEnumerable<T>
不)[編輯:這是不對的,第一個版本的用途BaseItem
,而不是T
;哎呀] - 重載(
GetItem
沒有超載,GetList
有幾個,我只需要在委託GetList()
沒有PARAMS
UPDATE1:薩姆幫我找出一些問題,如果的返回類型委託是通用的(例如IEnumerable<BaseItem>
),當我嘗試交換基類/派生類型時,它會窒息。有沒有什麼辦法可以聲明我的GetList
方法如下?我需要能夠指示繼承自BaseItem
,但是如果我那麼它可以爲我工作。
public static IEnumerable<BaseItem> GetList<T>() where T : class
另一種選擇是「通用化」我的委託聲明。我可以找到的所有示例都使用通用參數,而不是返回類型。我如何做到這一點(它拋出一個編譯器錯誤原因T
是不確定的,它不會讓我用where
約束):
public delegate IEnumerable<T> GetListDelegate();
在發佈之前的所有閱讀中,我知道類型不匹配是此異常的一個常見原因。我在上面每個例子中的返回調用中設置了一個斷點,並且在每種情況下變量方法的類型看起來幾乎相同。我什麼都看不到。只是想我會添加那個珍聞。 – sliderhouserules 2010-01-14 04:20:53
爲什麼這會變成社區維基? – sliderhouserules 2010-01-14 08:03:13
哇,你編輯自己的帖子夠了,它會自動變成一個維基?這是該死的愚蠢。 – sliderhouserules 2010-01-14 08:18:12