【问题标题】:Retrieving a collection from a generic method with a run time generic type从具有运行时泛型类型的泛型方法中检索集合
【发布时间】:2020-06-17 09:24:27
【问题描述】:

我有一个通用方法

var propertyResolverMethod = _propertyResolver
    .GetType()
    .GetMethod(
        nameof(_propertyResolver.GetEntities),
        new[] { typeof(string), typeof(string) })
    ?.MakeGenericMethod(_itemType);

和调用

var recommendedItems = propertyResolverMethod
    ?.Invoke(
        _propertyResolver,
        new object[] { itemId, ResolvedCollectionId });

它在编译时返回一个对象,但在运行时,它返回IQueryable<Item> 这个项目是来自 _itemType 的项目,我们只在运行时找到它的类型,但我知道它在 Item 中有一个集合.RelatedItems 我需要得到。已经尝试过转换为动态,但不适用于我的情况,我知道这可以通过表达式以某种方式解决。

应该像这样可迭代

var itemIds = recommendedItems?.Select(i => i.RelatedItems.Select(s => s.ItemID));

但如果没有适当的演员表,这是不可能的

【问题讨论】:

    标签: c# .net reflection


    【解决方案1】:

    嗯..

    因此,如果我理解正确,您知道此方法返回一个 IQueryable<Item>,其中 Item 是先前存储在 _itemType 中的类型,并且您还知道该类型总是定义 RelatedItems,而 RelatedItemsIEnumerable<T>IQueryable<T>Tdefining ItemID

    是否存在所有可能的_itemTypes 都继承自该类型并定义了RelatedItems?如果是这样,您可以尝试投射到那个...

    否则你可以做更多反射魔法: 如果您知道您的结果是 IQueryable<TItem>,您可以使用反射提取 RelatedItems 的属性获取器并将 that 传递给 Select-function(您可以通过将其转换为 @ 987654333@ 或再次使用 ... 反射。

    但老实说,这将是一种非常、非常肮脏的做法,我只会作为最后的手段。

    我现在的第一直觉是尝试重构包含类(_itemType 向我暗示这是一个成员字段),所以它也是通用的(如果需要,从非通用类继承) ,所以类知道通过它自己的类型参数的类型。

    另一种解决方案是拥有这样的功能:

    private <Type of itemIDs> GetRelatedItemIds<TItem>(object source) {
     return ((IQueriable<TItem>)source)?.Select(i => i.RelatedItems.Select(s => s.ItemID));
    }
    

    现在通过反射获取该方法并在其上使用MakeGenericMethod(_itemType),然后使用您的结果调用它。

    请注意,您当前的选择将返回一个嵌套的可枚举/可查询,其中每个条目都是 ItemID 的列表。如果您不想这样做,请使用SelectMany 而不是第一个Select,它将自动连接内部的枚举/查询。

    我希望这可以帮助您找到解决方案。

    【讨论】:

    • 很遗憾,我无法更改 _itemType
    • 而且它也是一个 IQueryable,我们不能简单地提取一个 getter 属性。应该使用我得到的表达式
    猜你喜欢
    • 2016-06-11
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多