【问题标题】:Cast object to a generic type将对象转换为泛型类型
【发布时间】:2013-05-23 15:25:33
【问题描述】:

我有一段时间没睡了,所以这可能比我想象的要容易。

我有一个或多或少的通用类:

public class Reference<T> where T : APIResource //<- APIResource is abstract btw
{
    private T _value = null;
    public T value
    { 
        get { return _value; }
    }
}

在其他地方,在自定义序列化方法中,有人传入了一个object,它实际上是Reference&lt;(something)&gt; 的一个实例。我只是想跳到每个Reference&lt;&gt; 对象具有的“值”属性,所以我想去:

string serialize(object o)
{
    return base.serialize( ((Reference<>) o).value );
}

当然,生活并没有那么简单,因为正如编译器所说:

using the generic type "Reference&lt;T&gt;" requires 1 type arguments

我怎样才能做我想做的事?

【问题讨论】:

    标签: c# generics serialization


    【解决方案1】:

    您可以使用该属性创建协变通用接口:

    interface IReference<out T> where T : ApiResource {
        T Value { get; }
    }
    

    然后您可以将IReference&lt;Anything&gt; 转换为IReference&lt;object&gt;IReference&lt;ApiResource&gt;

    【讨论】:

    • 我对协变泛型接口一无所知,所以我很高兴我转向 SO。我不得不相应地修改泛型类:public class Reference&lt;T&gt; : IReference&lt;T&gt; where T : APIResource { ... }。这使我可以使用 ((IReference&lt;APIResource&gt;) o).Value 检索 Value 属性
    【解决方案2】:

    SLaks 的答案是完美的。我只是想扩展一点:

    在某些情况下,您不能用接口替换类。 在这种情况下您可能需要使用dynamic 功能,以便您可以调用value 属性:

    string serialize(object o)
    {
        if(typeof(Reference<>) == o.GetType().GetGenericTypeDefinition())
            return base.serialize( ((dynamic)o).value );
    
        //in your case you will throw InvalidCastException
        throw new ArgumentException("not a Reference<>", "o"); 
    }
    

    这只是另一种选择,我建议非常小心地使用它。

    【讨论】:

    • 感谢您的替代方案。显然这是最后的手段,但非常重要的是,如果有人无法修改相关的泛型类。
    【解决方案3】:

    别忘了检查它是否是泛型类型---> o.GetType().IsGenericType, before

    使用 o.GetType().GetGenericTypeDefinition() 否则会抛出异常..

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多