从一般方法获取值而不提供类型

时间:2015-10-21 09:12:35

标签: c# generics

我试图创建一个类,其中一个属性是通用的,没有类本身是通用的。我发现你不能这样做;不允许使用通用属性。我对线程Making a generic property进行了一些挖掘,我找到了一个可以很好地为我工作的工作。

随后,我结束了这堂课......

[Serializable]
public class ConfigurationItem
{
    private readonly Type type;

    public string Description { get; set; }

    public IDictionary<string, ConfigurationItem> Items { get; private set; }

    public string Name { get; set; }

    public string Summary { get; set; }

    public object Value { get; private set; }

    public ConfigurationItem(string name, Type type = null, object value = null)
    {
        this.Name = name;
        this.type = type ?? typeof(string);
        this.Value = value;
        Items = new Dictionary<string, ConfigurationItem>();
    }

    public string Export()
    {
        return JsonConvert.SerializeObject(this);
    }

    public T GetValue<T>()
    {
        return (T)Convert.ChangeType(Value, type);
    }
}

现在唯一的问题是,如果我想获得值,正确投射,我必须在调用GetValue()时提供类型。本能地,我不禁感到,鉴于该类知道应该返回的类型,我应该可以构建一个GetValue()方法,不需要我提供任何其他信息。

我无法弄清楚如何。

我确实发现线程Getting a generic method to infer the type parameter from the runtime type似乎表明它是可能的,但我对Reflection很少了解,也无法理解所说的内容。

有没有办法构建一个GetType()方法,不需要我提供泛型类型?你能用一种我虚弱的大脑能理解它的方式解释它吗?

修改 很多人实际上已经指出,无论如何我真的不需要这样做,但作为一个学习练习我跟随@ShoaibShakeel的建议来查看C#dynamic类型并想出了这些额外的方法...

    public dynamic GetValue()
    {
        return typeof(ConfigurationItem)
            .GetMethod("GetReturnValue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
            .MakeGenericMethod(type)
            .Invoke(this, new object[] { });
    }

    private T GetReturnValue<T>()
    {
        return (T)Convert.ChangeType(Value, type);
    }

3 个答案:

答案 0 :(得分:1)

  

本能地,我不禁感到,因为该类知道应该返回的类型

虽然Value对象确实知道它自己的类型,但是这个信息仅在运行时可用(一旦有一个具有类型的实际对象)。因此,为了在编译时获得类型信息,您需要提供必要的信息。毕竟,不可能静态地知道在那里分配了什么对象。

但假设GetValue()能够自动返回类型对象,您想要用它做什么?

var x = configurationItem.GetValue();

那么x应该是什么类型,以及之后你想用它做什么?你只想打印它还是什么?那么object就足够了。你想用它计算一些东西吗?那么你已经要求它是intfloat或者其他东西,所以你需要一个实际的静态类型 - 这就是你必须提供那种类型信息的原因。

仅仅因为返回类型为object并不意味着对象本身会丢失类型信息。分配给object属性的字符串仍然是一个字符串,即使您稍后检索它也是如此。如果你期望一个字符串并希望用它做一些事情,那么你肯定可以将它转换为字符串。

答案 1 :(得分:0)

没有

编译器无法从它所分配的变量中推断出类型,因为它是不明确的,特别是在大型继承树中。

考虑一下

object o = configurationItem.GetValue<int>();

int可能是您的有效转化,但object不是,因为object未实现IConvertible接口({{1}需要}}

答案 2 :(得分:0)

我能够让我的类返回一个值,使用反射和动态来正确地投射,使用以下对我原始类的添加。

public dynamic GetValue()
{
    return typeof(ConfigurationItem)
        .GetMethod("GetReturnValue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
        .MakeGenericMethod(type)
        .Invoke(this, new object[] { });
}

private T GetReturnValue<T>()
{
    return (T)Convert.ChangeType(Value, type);
}