sli*_*les 5 c# generics delegates methodinfo
感谢 Jon Skeet 在这个问题中的回答,我进行了以下工作:
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
Run Code Online (Sandbox Code Playgroud)
当我尝试将相同的事情应用于具有不同返回类型和重载的方法时(这些是我能想到的唯一差异),我得到一个恼人的“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();
}
}
Run Code Online (Sandbox Code Playgroud)
如上所述,我能看到的唯一区别是:
T有效,IEnumerable<T>无效)[编辑:这是不对的,第一个版本使用BaseItem, not T; 哎呀]GetItem没有重载,有几个;我只需要没有参数的GetList委托GetList()Update1: Sam 帮助我查明了一些问题。如果委托的返回类型是通用的(例如IEnumerable<BaseItem>),当我尝试交换基本/派生类型时,它会令人窒息。有什么方法GetList可以像下面这样声明我的方法吗?我需要能够表明T继承自BaseItem,但如果我可以的话,那么它对我来说效果很好。
public static IEnumerable<BaseItem> GetList<T>() where T : class
Run Code Online (Sandbox Code Playgroud)
另一种选择是“通用化”我的委托声明。我能找到的所有示例都使用泛型作为参数,而不是返回类型。我该怎么做(它会引发编译器错误,原因T是未定义,并且不允许我使用where约束):
public delegate IEnumerable<T> GetListDelegate();
Run Code Online (Sandbox Code Playgroud)
我通过将代表声明为 just 来完成这项工作IEnumerable。这允许它创建委托。剩下的就只是基本的选角了。以下更改修复了上面的第二个代码块。
// declare this as non-generic
public delegate IEnumerable GetListDelegate();
Run Code Online (Sandbox Code Playgroud)
和
// do some cast-fu to get the list into a workable form
List<BaseItem> myList = getList().Cast<BaseItem>().ToList();
Run Code Online (Sandbox Code Playgroud)
然后我就可以myList.Sort()在工作时在我的系统中做所有其他我想做的事情。
| 归档时间: |
|
| 查看次数: |
6520 次 |
| 最近记录: |