C # определение универсального типа - PullRequest
6 голосов
/ 27 мая 2010

У меня есть несколько шаблонных объектов, которые реализуют один и тот же интерфейс:

И.Е.

MyObject<datatype1> obj1;
MyObject<datatype2> obj2;
MyObject<datatype3> obj3;

Я хочу сохранить эти объекты в списке ... Думаю, я бы сделал это так:

private List<MyObject<object>> _myList;

Затем я хочу создать функцию, которая принимает 1 параметр, являющийся типом данных, чтобы увидеть, существует ли объект, использующий этот тип данных, в моем списке…. В псевдокоде это будет:

public bool Exist(DataType T)
{
   return (does _myList contain a MyObject<T>?);
}

Некоторые разъяснения ....

Мой интерфейс IMyObject<T>, мои объекты MyObject<T>. У меня есть новый класс MyObjectManager, в котором мне нужно хранить список MyObject<T>. Мне нужна функция, чтобы проверить, существует ли MyObject<T> в этом списке. Тип T - это типы данных, которые были автоматически сгенерированы с использованием классов T4 .... POCO из моей модели данных сущностей.

Ответы [ 3 ]

6 голосов
/ 27 мая 2010

Вы можете сделать универсальную функцию:

public bool Exists<T>() where T : class {
    return _myList.OfType<MyObject<T>>().Any();
}

Обратите внимание, что для этого необходимо знать T во время компиляции.

Если все, что у вас есть, это System.Type объект во время выполнения, вам нужно использовать отражение:

public bool Exists(Type t) {
    var objectOfT = typeof(MyObject<>).MakeGenericType(t);

    return _myList.Any(o => o.GetType() == objectOfT);
}

Обратите внимание, однако, что List<MyObject<object>> не может содержать MyObject<SomeType>.
Вам нужно изменить список на List<object>, или заставить MyObject реализовать или наследовать неуниверсальный тип и сделать список, содержащий этот тип.

1 голос
/ 27 мая 2010

Как насчет метода расширения?

public static bool HasAny(this IEnumerable source, Type type) {
    foreach (object item in source)
        if (item != null && item.GetType().Equals(type))
            return true;

    return false;
}

Использование:

bool hasDataType1 = myList.HasAny(typeof(MyObject<datatype1>));

Обратите внимание, что если вы не хотите вводить typeof(...), т. Е. Если вы хотите, чтобы ваш Exist метод только заботился об объектах типа MyObject<T>, я пошел бы с чем-то вроде ответа SLaks:

public static bool Exist<T>(this IEnumerable source) {
    return source.OfType<MyObject<T>>().Any();
}

Кроме того, SLaks прав, что вы действительно не можете иметь List<MyObject<object>>, который полон чего-либо, кроме объектов типа MyObject<object> или некоторого производного класса (и MyObject<datatype1> и т. Д. Делают не происходят от MyObject<object> - генерики так не работают).

Другой способ, с помощью которого я мог бы предложить обойти всю проблему «вы не можете получить тип универсального класса, используя объект System.Type без использования отражения», заключается в следующем: заставить ваш MyObject<T> реализовать неуниверсальный интерфейс, как это:

public interface IMyObject {
    Type DataType { get; }
}

public class MyObject<T> : IMyObject<T>, IMyObject {
    public Type DataType {
        get { return typeof(T); }
    }
}

Тогда ваш список может быть List<IMyObject> (неуниверсальный интерфейс), а ваш Exist метод может выглядеть следующим образом:

public static bool Exist<T>(this IEnumerable source, Type type) {
    return source.OfType<IMyObject>().Any(x => x.DataType.Equals(type));
}
0 голосов
/ 27 мая 2010

Поскольку все они реализуют один и тот же интерфейс, вместо того, чтобы приводить их к объекту и вызывать GetType (что может быть дорого), почему бы не добавить в свой интерфейс свойство, называемое именем класса (или чем-то еще)? Затем вы можете использовать linq для того, чтобы получить это свойство. И не забудь using System.Linq

using System.Linq;

public bool Exist(List<IMyInterface> objects, IMyInterface typeToCheck)
{
   return objects.Any(t => t.ObjectName == typeToCheck.ObjectName);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...