简体   繁体   English

C#确定泛型类型

[英]C# determining generic type

I have several templated objects that all implement the same interface: 我有几个模板化的对象都实现了相同的接口:

IE IE

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

I want to store these objects in a List... I think I would do that like this: 我想将这些对象存储在List中...我想我会这样做:

private List<MyObject<object>> _myList;

I then want to create a function that takes 1 parameter, being a datatype, to see if an object using that datatype exists in my list.... sorta clueless how to go about this. 然后我想创建一个函数,它接受一个参数,作为数据类型,以查看我的列表中是否存在使用该数据类型的对象.... sorta无知如何去做。 In Pseudo code it would be: 在伪代码中它将是:

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

Some Clarification.... 一些澄清....

My interface is IMyObject<T> , my objects are MyObject<T> . 我的界面是IMyObject<T> ,我的对象是MyObject<T> I have a new class MyObjectManager which I need to have a List of MyObject<T> stored within. 我有一个新类MyObjectManager ,我需要在其中存储一个MyObject<T>列表。 I need a function to check if a MyObject<T> exists in that list. 我需要一个函数来检查该列表中是否存在MyObject<T> The type T are datatypes which were auto-generated using T4.... POCO classes from my Entity Data Model. 类型T是使用来自我的实体数据模型的T4 .... POCO类自动生成的数据类型。

You can make a generic function: 您可以创建一个通用函数:

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

Note that this requires that you know T at compile-time. 请注意,这需要您在编译时知道T

If all you have is a System.Type object at runtime, you'll need to use reflection: 如果您拥有的只是运行时的System.Type对象,则需要使用反射:

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

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

Note, however, that a List<MyObject<object>> cannot hold a MyObject<SomeType> . 但请注意, List<MyObject<object>> 无法保存MyObject<SomeType>
You need to change the list to a List<object> , or make MyObject implement or inherit a non-generic type and make the list contain that type. 您需要将列表更改为List<object> ,或使MyObject实现或继承非泛型类型并使列表包含该类型。

How about an extension method? 扩展方法怎么样?

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;
}

Usage: 用法:

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

Note that if you don't want to have to type out typeof(...) -- ie, if you basically want your Exist method to only care about objects of type MyObject<T> , I'd go with something like SLaks's answer: 请注意,如果您不想输入typeof(...) - 也就是说,如果您基本上希望您的Exist方法关心MyObject<T>类型的对象,那么我会选择像SLaks这样的东西。回答:

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

Also, SLaks is right that you really can't have a List<MyObject<object>> that's full of anything other than objects of type MyObject<object> or some derived class (and MyObject<datatype1> , etc. do not derive from MyObject<object> -- generics don't work that way). 另外,SLaks是正确的,你真的不能有一个List<MyObject<object>> ,除了MyObject<object>类型的MyObject<object>或者某些派生类(和MyObject<datatype1>等)之外,其他任何东西都不是派生自MyObject<object> - 泛型不起作用)。

Another way I might suggest to work around the whole "you can't get the type of a generic class using a System.Type object without using reflection" issue would be this: Make your MyObject<T> implement a non-generic interface, like this: 我可能建议解决整个问题的另一种方法是“你不能使用System.Type对象而不使用反射来获取泛型类的类型”问题:将MyObject<T>实现为非泛型接口,像这样:

public interface IMyObject {
    Type DataType { get; }
}

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

Then your list could be a List<IMyObject> (the non-generic interface) and your Exist method could look like this: 然后你的列表可能是List<IMyObject> (非泛型接口),你的Exist方法可能如下所示:

public static bool Exist<T>(this IEnumerable source, Type type) {
    return source.OfType<IMyObject>().Any(x => x.DataType.Equals(type));
}

Since they all implement the same interface, instead of casting them to object and calling GetType (which can be expensive) why not add a property to your interface called class name (or something)? 因为它们都实现了相同的接口,而不是将它们转换为对象并调用GetType(这可能很昂贵)为什么不在你的接口中添加一个名为class name(或者其他东西)的属性? Then you can use the linq in order to grab that property. 然后你可以使用linq来获取该属性。 And don't forget using System.Linq 不要忘记using System.Linq

using System.Linq;

public bool Exist(List<IMyInterface> objects, IMyInterface typeToCheck)
{
   return objects.Any(t => t.ObjectName == typeToCheck.ObjectName);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM