制作通用属性


74

我有一个存储序列化值和类型的类。我想要一个属性/方法返回已经强制转换的值:

public String Value { get; set; }

public Type TheType { get; set; }

public typeof(TheType) CastedValue { get { return Convert.ChangeType(Value, typeof(_Type)); }

这在C#中可能吗?


4
通用属性会很好。我认为var val = obj.Prop<Type>,基于类型的查找比obj.Prop[typeof(Type)]or更为简洁obj.GetProp<Type>()
Dan Lugg

Answers:


106

如果包含该属性的类是通用的,并且使用通用参数声明该属性,则是可能的:

class Foo<TValue> {
    public string Value { get; set; }
    public TValue TypedValue {
        get {
            return (TValue)Convert.ChangeType(Value, typeof(TValue));
        }
    }
}

一种替代方法是改为使用通用方法:

class Foo {
    public string Value { get; set; }
    public Type TheType { get; set; }

    public T CastValue<T>() {
         return (T)Convert.ChangeType(Value, typeof(T));
    }
}

您还可以使用System.ComponentModel.TypeConverter类进行转换,因为它们允许类定义其自己的转换器。

编辑:请注意,在调用泛型方法时,必须指定泛型类型参数,因为编译器无法推断出它:

Foo foo = new Foo();
foo.Value = "100";
foo.Type = typeof(int);

int c = foo.CastValue<int>();

您必须在编译时知道类型。如果您在编译时不知道类型,则必须将其存储在中object,在这种情况下,可以将以下属性添加到Foo类中:

public object ConvertedValue {
    get {
        return Convert.ChangeType(Value, Type);
    }
}

在类“ Foo”的第二个示例中,我感到困惑:一个公共属性“ theType被声明为:“ public Type TheType {get; set;}”,但似乎未在代码中使用。谢谢,
BillW

该属性在原始示例中。我只是留在里面了
。– Brannon

当我尝试使用Brannons解决方案时,出现运行时错误,提示我正在投射的对象必须实现IConvertible。我做错了什么吗,因为除非在我有可用资源的地方进行授课,否则这似乎会破坏交易。
基思

59

属性,事件,构造函数等不能通用-只有方法和类型可以通用。多数情况下这不是问题,但我同意有时会很痛苦。布兰农的答案给出了两个合理的解决方法。


5

我不认为您在此处给出的示例是可行的。必须在编译时定义CastedValue的类型,这意味着它不能依赖于运行时值(TheType属性的值)。

编辑:布兰农的解决方案有一些很好的想法,如何使用泛型函数而不是属性来处理此问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.