我有一个通用的方法:
Func<IEnumerable<T>, bool> CreateFunction<T>()
其中T
可以是任意数量的不同类型。这个方法使用反射做了很多东西,如果T
是IDictionary
,无论字典的TKey
和TValue
我需要执行字典特定的代码。
因此可以调用该方法:
var f = CreateFunction<string>();
var f0 = CreateFunction<SomePocoType>();
var f1 = CreateFunction<IDictionary<string,object>>();
var f2 = CreateFunction<Dictionary<string,object>>();
var f3 = CreateFunction<SomeDerivedDictionaryType<string,object>>();
等
根据@Andy的答案澄清
最终我想知道T
是否继承自/ IDictionary
,即使T
本身是Dictionary
,也可能是从该接口派生的其他类型。
if(typeof(T) == typeof(IDictionary<,>)
不起作用,因为T
是泛型类型而不是泛型类型定义。
在不知道TKey
和TValue
(编译时不知道)的情况下,我无法与运行时知道的任何具体类型进行比较。
我唯一想到的就是查看类型的名称或使用反射检查其方法,寻找可以让我相信它是字典的方法(即查找ContainsKey
和{ {1}})。
有没有直接的方法来做出这种决定?
答案 0 :(得分:7)
您可以避免使用IsGenericType和GetGenericTypeDefinition成员使用丑陋且具有潜在风险的类型名称字符串检查,如下所示:
var type = typeof (T);
if (typeof (IDictionary).IsAssignableFrom(type))
{
//non-generic dictionary
}
else if (type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof (IDictionary<,>))
{
//generic dictionary interface
}
else if (type.GetInterfaces().Any(
i => i.IsGenericType &&
i.GetGenericTypeDefinition() == typeof (IDictionary<,>)))
{
//implements generic dictionary
}
答案 1 :(得分:4)
简单的方法就是:
Type iDict = null;
if (typeof(T).GetGenericTypeDefinition() == typeof(IDictionary<,>))
iDict = typeof(T);
else
iDict = typeof(T).GetInterface(typeof(IDictionary<,>).Name);
if (iDict != null)
{
var genericParams = iDict.GetGenericArguments();
Type tKey = genericParams[0], tValue = genericParams[1];
}
请注意,如果T
实现多个 IDictionary<,>
接口,则无效(抛出异常),但这可能适用于您的目的。
为了完整起见,这是一个将使用第一个接口来处理具有多个IDictionary<,>
接口的类型的实现:
Type iDict = t.GetType().GetInterfaces()
.Where(t => t.IsGenericType
&& t.GetGenericTypeDefinition() == typeof(IDictionary<,>))
.FirstOrDefault();
if (iDict != null)
{
var genericParams = iDict.GetGenericArguments();
Type tKey = genericParams[0], tValue = genericParams[1];
}
请注意,在第二个例程中,t
是一个对象,而T
是第一个例程中的一个类型。
答案 2 :(得分:2)
您可以执行类似
的操作class Program
{
static void Main(string[] args)
{
Example<IDictionary<int, string>>.IsDictionary();
Example<SortedDictionary<int, string>>.IsDictionary();
Example<Dictionary<int, string>>.IsDictionary();
Console.ReadKey();
}
}
public class Example<T>
{
public static void IsDictionary()
{
if (typeof(T).GetInterface(typeof(IDictionary<,>).Name) != null || typeof(T).Name.Contains("IDictionary"))
{
Console.WriteLine("Is IDictionary");
}
else
{
Console.WriteLine("Not IDictionary");
}
}
}
答案 3 :(得分:0)
我认为如果你调用Type.GetGenericTypeDefinition()应该返回用于构造具体类型的“基础”泛型类型。
请注意,仅将此与IDictionary<,>
进行比较可能还不够,因为如果有人传入Dictionary<,>
的实例,我认为您也希望使用它。您可以检查Type是否实现IDictionary<,>
,或者您可以调用Type.IsAssignableFrom(),尽管根据文档,我不确定这对于泛型类型有多好。