Получение коллекции из метода generi c с типом generi c времени выполнения - PullRequest
1 голос
/ 17 июня 2020

У меня есть общий c метод

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, которую мне нужно получить. Пробовал уже приведение к динамическому c, но не работает в моем случае, я знаю, что это как-то решается с помощью выражений.

Должно быть итеративным, как это

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

Но это невозможно без правильный слепок

1 Ответ

0 голосов
/ 17 июня 2020

Хмм ..

Итак, если я вас правильно понял, вы знаете, что этот метод возвращает IQueryable<Item>, где Item - это тип, ранее сохраненный в _itemType, и вы также знаете, что этот type всегда определяет RelatedItems, которые, в свою очередь, являются IEnumerable<T> или IQueryable<T> с T, определяющим ItemID?

Есть ли тип, который все возможные _itemTypes наследуют от того, который имеет RelatedItems определены? Если это так, вы можете попробовать выполнить приведение к этому ...

В противном случае вы могли бы сделать больше Reflection magi c: Если вы знаете, что ваш результат - IQueryable<TItem>, вы можете извлечь свойство-геттер для RelatedItems с Reflection и передайте , что функции Select (которую вы можете получить путем преобразования в IQueryable<object> или с помощью ... снова ... Reflection.

Но чтобы честно говоря, это был бы очень и очень грязный способ сделать это, и я бы сделал это только в крайнем случае.

Моим первым побуждением было бы попробовать рефакторинг содержащего класса (_itemType намекает на мне, что это поле-член), поэтому оно также является generi c (наследуется от не-generi c класса, если вам это нужно), поэтому класс знает тип через свой собственный параметр типа.

Другое решение - иметь такую ​​функцию:

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

Теперь получите этот метод через Reflection и используйте на нем MakeGenericMethod(_itemType), затем вызовите его с вашим результатом.

Учтите, что ваш текущий выбор вернет ested enumerable / queryable, каждая запись которого является списком ItemID. Если вы не хотели этого делать, используйте SelectMany вместо первого Select, который автоматически объединит внутренние перечисления / запросы.

Надеюсь, это поможет вам найти решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...