【问题标题】:Derived Types and Generics派生类型和泛型
【发布时间】:2016-06-01 13:56:34
【问题描述】:

我有一个使用泛型的类型。让我们称之为FlowerDescriptor<T> 一些花是用数字来描述的,另一些是用字符串等来描述的。

所以FlowerDescriptor<int>;FlowerDescriptor<string>;等等

我想要一种机制(可能是扩展方法)来做两件事

  • 看看有没有东西FlowerDescriptor
  • 查看描述符是什么。

  • FlowerDescriptor<string>.GetType().IsFlowerDescriptor == true string.GetType().IsFlowerDescriptor == false

同样,我可能来自FlowerDescriptor&lt;int&gt;,即class NumberedFlower: FlowerDescriptor&lt;int&gt;

new NumberedFlower.GetType().IsFlowerDesriptor == true;

  • 同上,但返回类型 FlowerDescriptor<string>.GetType().GetFlowerDescriptor() == typeof(string) FlowerDescriptor<int>.GetType().GetFlowerDescriptor() == typeof(int) new NumberedFlower.GetType().GetFlowerDescriptor() == typeof(int)

我玩过IsAssignableFrom 的变体,感觉这应该适用于typeof(FlowerDescriptor&lt;&gt;).IsAssignableFrom(typeof(FlowerDescriptor&lt;string&gt;))

但它不起作用。如果它添加泛型类型,它会这样做。

我目前正在探索GetInterfaces 以了解可用的接口。能真正理解我做错了什么也很棒..

【问题讨论】:

    标签: c# .net generics inheritance


    【解决方案1】:

    除非您想在组合中添加接口,否则您唯一的选择就是

    1. 检测到类型实际上是FlowerDescriptor&lt;T&gt;
    2. 或检测到类型继承来自FlowerDescriptor&lt;T&gt;

    不幸的是,当涉及到开放泛型时,我认为您不能使用 IsAssignableFrom,这意味着我们只能将继承链一直延伸到基类。

    这是一个可以做正确事情的示例代码:

    public static bool IsFlowerDescriptor(this Type type)
    {
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(FlowerDescriptor<>))
            return true;
        if (type.BaseType != null)
            return type.BaseType.IsFlowerDescriptor();
    
        return false;
    }
    

    这是一个.NET Fiddle,您可以尝试一下。

    【讨论】:

    • 这看起来最接近。如果 FlowerDesriptor 不是基本类型和/或它不是直接派生的类型,这会起作用吗?即它可以走树并在其中的任何地方找到它。
    • 另外,混合接口?怎么样..在生产中它会是 IFlowerDescriptor
    【解决方案2】:

    我不希望 string 或 int 类知道它是否是描述符,从 FlowerDescriptor 获取该信息更有意义。

    也就是说,如果你想使用反射,你可以从 FlowerDescriptor 实例中获取泛型类型定义

    FlowerDescriptor<int> f = new FlowerDescriptor<int>();
    Type t = f.GetType();
    Type[] typeArguments = t.GetGenericArguments();
    //check if type you care about is in typeArguments
    

    【讨论】:

      【解决方案3】:

      以下是获取这两个值的方法:

      bool isFlowerDescriptor = x is FlowerDescriptor<object>;
      
      Type descriptorType = x.GetType().GetGenericArguments()[0];
      

      如果您愿意,您可以将它们包装在扩展方法中。并添加空检查等。

      【讨论】:

        【解决方案4】:

        您可能会考虑使用非泛型基类。那么你的结构可能如下所示:

        public abstract class FlowerDescriptor { }
        
        public class FlowerDescriptor<T> : FlowerDescriptor { }
        
        public class NumberedFlower : FlowerDescriptor<int> { }
        

        您的 2 个扩展名将是:

        public static class Extensions
        {
            public static bool IsFlowerDescriptor(this object o)
            {
                return o is FlowerDescriptor;
            }
        
            public static Type GetFlowerDescriptor<T>(this FlowerDescriptor<T> o)
            {
                return typeof (T);
            }
        }
        

        你会像这样使用它:

        public static void Main()
        {
            Console.WriteLine(new NumberedFlower().IsFlowerDescriptor());  //true
            Console.WriteLine(new NumberedFlower().GetFlowerDescriptor()); //System.Int32
        }
        

        泛型在反射和比较类型时会产生不利影响,因为FlowerDescriptor&lt;int&gt;FlowerDescriptor&lt;string&gt; 是不同的类型。这是我没有找到好的节奏。

        【讨论】:

        • 谢谢 - 但我不想更改实现以满足此要求。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-03-22
        • 1970-01-01
        • 2011-10-09
        • 2012-09-08
        • 2014-06-19
        • 2011-05-24
        • 2019-04-15
        相关资源
        最近更新 更多