确定字段是否使用通用参数

时间:2016-10-21 14:10:46

标签: c# generics reflection

我对此感到困惑,似乎无法理解我的想法,所以希望有人能指出我正确的方向。

我有一个课程如下:

var notifyBeforeAvailability: Int!
var ratePerMin: Float!


notifyBeforeAvailability = 1
updateNotifyBeforeAvailability()
ratePerMin = 0.10
updateRatePerMin()


 @IBAction func notifyBeforeAvailabilityPlus(sender: AnyObject) {
    notifyBeforeAvailability = notifyBeforeAvailability + 1
    updateNotifyBeforeAvailability()
}
@IBAction func notifyBeforeAvailabilityMinus(sender: AnyObject) {
    notifyBeforeAvailability = notifyBeforeAvailability - 1
    updateNotifyBeforeAvailability()
}
func updateNotifyBeforeAvailability() {
    lblNotifyTime.text = String(notifyBeforeAvailability) + "min"
}


@IBAction func ratePerMinPlus(sender: AnyObject) {
    ratePerMin = ratePerMin + 0.10
    updateRatePerMin()
}    
@IBAction func ratePerMinMinus(sender: AnyObject) {
    ratePerMin = ratePerMin - 0.10
    updateRatePerMin()
}
func updateRatePerMin() {
    let currentValue = ratePerMin
    let current_string = String.localizedStringWithFormat("%.2f", currentValue)
    lblYourRate.text = "$" + current_string
}

现在我正在编写代码来反映这个类,并希望找到一种方法来确定字段Data是否具有正在使用的泛型参数。

我最初的方法是继续向下尽可能多的级别,一旦我将IsGenericParameter字段设置为true,我宁愿反映类型名称,而是放置一个" Generic Argument"那里的字符串,但我似乎无法按照我想要的方式工作。

我环顾四周,但我发现的每一个解决方案似乎都指向目前的死胡同。

2 个答案:

答案 0 :(得分:3)

您需要IsGenericType,而不是IsGenericParameter

bool isGeneric = typeof(Foo<int>).GetField("Data").FieldType.IsGenericType;

如果您想知道List的参数是通用的,那么您必须再看一级:

bool isGeneric = typeof(Foo<>).GetField("Data")
                                 .FieldType
                                 .GetGenericArguments()[0] // only generic argument to List<T>
                                 .IsGenericParameter;
  

如果Data字段是Dictionary Dictionary<string, T>,该怎么办?我如何确定使用通用参数的类型?

在类型上调用GetGenericArguments并查看结果数组中的每个类型

public class Foo<T>
{
    public Dictionary<string, T> Bar;
}

Type[] types = typeof(Foo<>).GetField("Bar").FieldType.GetGenericArguments();

Console.WriteLine("{0}\n{1}",
    types[0].IsGenericParameter,  // false, type is string
    types[1].IsGenericParameter   // true,  type is T
);

基本上,在查看类型的泛型参数时会使用IsGenericParameter来查看它是否是通用的,或者是否具有sepcified类型。

答案 1 :(得分:1)

以下是如何区分依赖类类型参数的泛型类型与不符合类型参数的泛型类型。考虑这个例子:

class Foo<T> {
    public List<T> field1;   // You want this field
    public List<int> field2; // not this field
}

首先获取泛型类型定义,并拉出其类型参数:

var g = typeof(Foo<string>).GetGenericTypeDefinition();
var a = g.GetGenericArguments();

这将为您提供一个表示泛型类型参数T的单一类型的数组。现在,您可以浏览所有字段,并在字段类型的泛型类型参数中搜索该类型,如下所示:

foreach (var f in g.GetFields()) {
    var ft = f.FieldType;
    if (!ft.IsGenericType) continue;
    var da = ft.GetGenericArguments();
    if (da.Any(xt => a.Contains(xt))) {
        Console.WriteLine("Field {0} uses generic type parameter", f.Name);
    } else {
        Console.WriteLine("Field {0} does not use generic type parameter", f.Name);
    }
}

此代码produces the following output

Field field1 uses generic type parameter
Field field2 does not use generic type parameter