一、缘起
最近做项目,碰到一个很有意思的问题,虽然不是很难,但是在网络上看到资料却很少,我想这或许又是另一个被容易忽略的话题。
问题是这样的:项目中用到一个类,他有一个保存数据的属性Value,这个属性有个比较奇怪的地方就是,他的类型,是无法预先估计的,会随着软件的扩展而变化,也就是我们常说的动态类型。
二、分析问题
这个问题解决方法很容易就可以看出有2种:
1、使用object基类
使用这种方式能够解决问题,但是会引起装箱、拆箱等影响性能的低效操作,不可取;
2、使用泛型类
使用泛型类也是能够解决问题的,但是在所有使用该对象时指出具体的类型,而这个会让上层使用该类时因具体类不同而不好组织,也不可取;
三、解决问题
为了避免伤处麻烦,我采用了泛型类 + 泛型方法的模式来解决问题,简单的说,就是
1、把Value的类型抽象出来做成一个类,我们称他为DynamicValue,这个类含有DataType来存储Value的数据类型,并提供了泛型方法GetValue和SetValue来读写Value的值。
2、在从DynamicValue上,派生一个泛型类DynamicValue<T>,用来实际存储数据。
使用这个方法的好处就是,避免了使用object会产生的装箱、拆箱动作,封装了泛型类的具体类型变化,更加容易管理和使用了。
四、具体实现看下面的代码:
/// <summary>
/// 动态数据类型
/// </summary>
public class DynamicValue
{
public string DataType { get; protected set; }
/// <summary>
/// 获取值之泛型方法
/// </summary>
/// <typeparam name="T">值类型</typeparam>
/// <returns>
/// 值
/// </returns>
public T GetValue<T>()
{
if (DataType == typeof(T).ToString())
{
return ((DynamicValue<T>)this).Value;
}
return default(T);
}
/// <summary>
/// 设置值之泛型方法
/// </summary>
/// <typeparam name="T">值类型</typeparam>
/// <param name="value">待复制参数</param>
/// <returns>
/// false:设置失败
/// true:设置成功
/// </returns>
public bool SetValue<T>(T value)
{
if (DataType == typeof(T).ToString())
{
((DynamicValue<T>)this).Value = value;
return true;
}
return false;
}
}
/// <summary>
/// 动态数据类型之泛型类
/// </summary>
/// <typeparam name="T"></typeparam>
public class DynamicValue<T> : DynamicValue
{
/// <summary>
/// 保存值
/// </summary>
public T Value { get; set; }
/// <summary>
/// 构造函数
/// </summary>
public DynamicValue()
: this(default(T))
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="value"></param>
public DynamicValue(T value)
{
Value = value;
DataType = typeof(T).ToString();
}
}
五、测试代码
class Program
{
static void Main(string[] args)
{
DynamicValue data = new DynamicValue<float>(12.3f);
Console.WriteLine("类型正确,返回应有的值");
Console.WriteLine(data.GetValue<float>());
Console.WriteLine("类型不匹配,返回default(T),即:值类型为0,引用类型为null");
Console.WriteLine(data.GetValue<TestValue>());
data = new DynamicValue<TestValue>(new TestValue());
Console.WriteLine("类型不匹配,返回default(T),即:值类型为0,引用类型为null");
Console.WriteLine(data.GetValue<float>());
Console.WriteLine("类型正确,返回应有的值");
Console.WriteLine(data.GetValue<TestValue>());
Console.Write("Press any key to exit..");
Console.ReadKey();
}
}
class TestValue
{
public int Value { get; set; }
public override string ToString()
{
return "Value = " + Value.ToString();
}
}
六、测试结果类型正确,返回应有的值
12.3
类型不匹配,返回default(T),即:值类型为0,引用类型为null
类型不匹配,返回default(T),即:值类型为0,引用类型为null
0
类型正确,返回应有的值
Value = 0
Press any key to exit..