Как привести объект в общую коллекцию? - PullRequest
1 голос
/ 01 марта 2012

Мне нужно преобразовать объект в общую коллекцию, смотрите:

var currentEntityProperties = currentEntity.GetType().GetProperties();

foreach (var currentEntityProperty in currentEntityProperties)
{
    if (currentEntityProperty.PropertyType.GetInterfaces().Any(
                x => x.IsGenericType &&
                x.GetGenericTypeDefinition() == typeof(ICollection<>)))
    {
        var collectionType = currentEntityProperty.PropertyType.GetInterfaces().Where(
                                x => x.IsGenericType &&
                                x.GetGenericTypeDefinition() == typeof(ICollection<>)).First();

        var argumentType = collectionType.GetGenericArguments()[0];

        // now i need to convert the currentEntityProperty into a collection, something like that (this is wrong, so, what is thr right way?):
        var currentCollection = (ICollection<argumentType.GetType()>)currentEntityProperty.GetValue(currentEntity, null);
    }
}

Как я могу это сделать?

Obs: мне нужно с этой коллекцией вызвать метод кроме с другой коллекцией (эту коллекцию я получаю с тем же способом currentCollection, с anotherEntityProperty.GetValue(anotherEntity, null))

var itens = currentCollection.Except(anotherCollection);

Ответы [ 4 ]

4 голосов
/ 01 марта 2012

Динамическая типизация позволяет заставить компилятор и DLR выполнять всю работу здесь:

dynamic currentCollection = ...;
dynamic anotherCollection = ...;
dynamic items = Enumerable.Except(currentCollection, anotherCollection);

Во время выполнения это сделает всю работу по отражению за вас и выберет наиболее подходящий аргумент типа.

1 голос
/ 01 марта 2012

Для метода расширения Except вам нужен только IEnumerable<T>, который реализует ICollection<T>. Таким образом, вы можете привести свое свойство к IEnumerable<object> (по крайней мере, если T является ссылочным типом).

РЕДАКТИРОВАТЬ:

Если вы действительно хотите, вы можете попробовать вызвать Except для переменных объекта путем отражения:

// x and y are your object variables of the collections, 
// argumentType is the generic type you determined
  var methods = from m in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
              where m.ContainsGenericParameters
              && m.Name == "Except"
              && m.GetParameters().Count() == 2
              && m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
              && m.ReturnType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
              select m;
  var method = methods.First();
  IEnumerable things = method.MakeGenericMethod(new Type[] { argumentType }).Invoke(null, new [] { x, y }) as IEnumerable;
0 голосов
/ 01 марта 2012

Это не отвечает на ваш вопрос напрямую, а скорее отвечает на вопрос нашего обсуждения в комментариях:

Как я могу вызвать метод Except, используя отражение?

Метод Except не является членом ICollection<T>, поэтому ваш вызов GetMethod возвращает null.Скорее, это метод расширения, определенный для статического типа System.Linq.Enumerable.Чтобы вызвать это с помощью рефлексии, вы должны рассматривать это как статический метод.Примерно так:

// there are two overloads of Except and I'm too lazy to construct the type parameters to get the correct overload
var methods = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public);
var exceptMethod = methods.Where(m => m.Name.Equals("Except") && m.GetParameters().Lengh == 2).Single();

object[] arguments = new [] { currentCollection, anotherCollection };
object items = exceptMethod.Invoke(null, arguments);

Вот "простой способ" Джона Скита (C # 4.0 и позже):

dynamic items = Enumerable.Except((dynamic)currentCollection, (dynamic)anotherCollection);
0 голосов
/ 01 марта 2012

Вы не можете использовать ICollection<some_type_determined_at_run_time> - компилятор не сможет создать для него никакого значимого кода.

Если приведение типов связано с ICollection<Base_Class>, должно работать в 4.0 - неправильно ... Такое приведение работает для IEnumerable (так как он имеет тип "out T" как тип), но не для ICollection.

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