gpt4 book ai didi

c# - MethodInfo、CreateDelegate 和通用方法

转载 作者:行者123 更新时间:2023-11-30 12:18:31 27 4
gpt4 key购买 nike

感谢 Jon Skeet 在 this 中的回答问题我有以下工作:

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:绑定(bind)到目标方法时出错。”正在调用 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();
}
}

如上所述,我能看到的唯一区别是:

  1. 不同的返回类型(T 有效,IEnumerable<T> 无效)[编辑:这是不对的,第一个版本使用 BaseItem , 不是 T ;哎呀]
  2. 重载(GetItem 没有重载,GetList 有几个;我只需要没有参数的委托(delegate)给 GetList()

更新 1:Sam 帮助我查明了一些问题。如果委托(delegate)的返回类型是通用的(例如 IEnumerable<BaseItem> ),当我尝试交换基本类型/派生类型时它会令人窒息。有什么办法可以申报我的 GetList方法如下?我需要能够指出 T继承自 BaseItem ,但如果我可以的话,它对我来说会很好。

public static IEnumerable<BaseItem> GetList<T>() where T : class

另一种选择是“通用化”我的委托(delegate)声明。我能找到的所有示例都对参数使用泛型,而不是返回类型。我该怎么做(它会抛出一个编译器错误,因为 T 未定义,而且它不会让我使用 where 约束):

public delegate IEnumerable<T> GetListDelegate();

最佳答案

我通过将委托(delegate)声明为 IEnumerable 来实现这一点。这允许它创建委托(delegate)。剩下的就是基本的类型转换。以下更改修复了上面的第二个代码块。

// declare this as non-generic
public delegate IEnumerable GetListDelegate();

// do some cast-fu to get the list into a workable form
List<BaseItem> myList = getList().Cast<BaseItem>().ToList();

然后我可以执行 myList.Sort() 以及我在工作中尝试在我的系统中执行的所有其他操作。

关于c# - MethodInfo、CreateDelegate 和通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2062084/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com