我有一个类,它具有下面给出的泛型类型的属性。类型T可以是任何数字(short,int,float…)
public class EqualFilter <T> : Filter {
private T _value;
public override T Value {
get {
return _value;
}
set {
if (!EqualityComparer<T>.Default.Equals(_value, value)) {
_value = value;
RaiseFilteringChanged();
}
}
}
.....
}
现在我有一个客户端类,它有一个"String",需要传递给上面的setter。现在,在上面的setter中设置值时,类型T已经在运行时确定,我可以在客户端中将该类型作为类型T。是否可以在客户端程序中将字符串转换为EqualFilter标识的适当类型?像这样的东西不起作用
Type T = filter.getFilterType();
filter.Value = (T) myTextBox.Text;
下面的代码可以工作,但它将涉及所有可以是数字的类型的if-else。
Type T = filter.getFilterType();
if (T == typeof(int)) {
filter.Value = Int32.Parse(myTextBox.Text);
} else if() {
....
}
简而言之,我不知道如何更好地处理这个问题。
听起来你在做类似于数据绑定的事情。如果您感兴趣的只是处理字符串,那么可以考虑将泛型类型约束为IConvertible
,并从一个特殊的setter方法调用Convert.ChangeType
方法,如
public class EqualFilter<T> : Filter where T : IConvertible {
// ... omitted Value property code ...
public void SetValue(string value)
{
Value = (T)Convert.ChangeType(value, typeof(T));
}
// ...
}
泛型类型约束只允许Convert.ChangeType可以操作的那些类型。除了积分和浮点类型之外,这还允许使用类型string
、decimal
和DateTime
。请注意,在使用double
类型时,string
类型可能并不总是精确的,因为可能存在舍入和浮点表示错误。此外,您可能还想捕获其他异常,以使其更加健壮(例如,FormatException
和OverflowException
)。
void Main()
{
var a = new EqualFilter<int> { Value = 10 };
var b = new EqualFilter<double> { Value = 20 };
b.Value = Math.PI; // RaiseFilteringChanged called - no surprise
b.SetValue(Math.PI.ToString()); // RaiseFilteringChanged called - surprised?
Console.WriteLine(b.Value);
b.SetValue("25");
Console.WriteLine(b.Value);
var c = new EqualFilter<DateTime> { Value = DateTime.Today };
Console.WriteLine(c.Value);
c.SetValue("12/23/2011");
Console.WriteLine(c.Value);
// compiler error object isn't an IConvertible:
// var illegal = new EqualFilter<object>();
}
在这种情况下,big-switch语句由ChangeType
方法中的框架处理。
编辑:添加上面代码版本的Console.WriteLine
输出(注释掉了重写和基类用法):
3.14159265358979
25
2012年4月10日凌晨12:00:00
2011年12月23日凌晨12:00:00
您可以尝试以下操作:
filter.Value = Convert.ChangeType(myTextBox.Text, filter.getFilterType());
如果没有定义转换,这将不起作用。
编辑:
我没有注意到你的Value
属性是通用的。为了实现这一点,你可以通过以下方式扩展你的过滤器对象:
public object UnsafeValue
{
set
{
Value = (T)value;
}
}
并将CCD_ 13的结果分配给该属性。
每一种不修改过滤器类的方法都会在调用层次结构或反射中涉及更多的泛型。
您是否考虑过创建这样一个特定的setter方法:
public void setValue(object o){
if (typeof(o) == typeof(Value)) {
Value = (typeof(Value))o;
}
}