C#通过IConvertible接口来实现自定义类型转换和计算
来源:互联网 发布:linux项目经理招聘 编辑:程序博客网 时间:2024/06/06 05:41
如果有一个需求,用户输入数据类型和操作符号的字符串,你需要根据这些字符串来分析出用户想要的结果。
比如用户输入的是:"int","123","-","int","111",如果是这样的字符串,那么你应该读作int类型的123-111,结果为12。
又比如用户输入的是:"datetime","2011-07-03","<","datetime","2010-05-01",这样的字符串是用户想进行datetime类型的数据的大小比较,结果为false。
我的设计思路是:
首先我要能识别出用户输入的这些类型,比如上面举例的int和datetime。这里有两种办法,第一我可以枚举返回系统定义的int和datetime,第二我可以枚举我自己定义的int和datetime,我的想法是枚举我自定义的,因为我还需要解析操作符号,系统定义的数据类型没办法去解析我自己定义的操作符号。
其次我要能识别出操作符号,以及知道这些操作符号应该进行一个什么样的运算。设想还是使用枚举来完成。
C#中一个很好用的函数是Convert.ChangeType,它允许用户将某个类型转换成其他类型。但是如何你需要转换的对象不是继承自IConvertible接口,那么系统会抛出异常,转换就失败了。
1.定义一个接口
public interface IUserDataType{ bool isGreater(IUserDataType obj1); bool isSmaller(IUserDataType obj1); bool isMoreOrEqual(IUserDataType obj1); bool isLessOrEqual(IUserDataType obj1); bool isEqual(IUserDataType obj1); bool isUnEqual(IUserDataType obj1);}
这个接口中可以定义一些你所需要的操作符号的函数,为的就是枚举对应到操作符的识别。
2.定义一个父类,这个类继承自上面的接口
public abstract class UserDataType : IUserDataType{ public abstract bool isGreater(IUserDataType obj1); public abstract bool isSmaller(IUserDataType obj1); public abstract bool isMoreOrEqual(IUserDataType obj1); public abstract bool isLessOrEqual(IUserDataType obj1); public abstract bool isEqual(IUserDataType obj1); public abstract bool isUnEqual(IUserDataType obj1); public static Type getType(string typeName) { switch (typeName) { case "int": return typeof(UserInt); case "datetime": return typeof(UserDateTime); case "decimal": return typeof(UserDecimal); case "string": return typeof(UserString); } return null; }}
注意一点,操作符号对应的函数使用abstract描述。另外,这个类中有一个static的函数是为了枚举得到所需要的type。
3.定义一个int类型,继承自父类
public class UserInt : UserDataType{ private int int_value; public UserInt() { int_value = 0; } public UserInt(int mvalue) { int_value = mvalue; } public string toString() { return int_value.ToString(); } public static bool operator ==(UserInt value1, UserInt value2) { return value1.int_value == value2.int_value; } public static bool operator !=(UserInt value1, UserInt value2) { return value1.int_value != value2.int_value; } public static bool operator >(UserInt value1, UserInt value2) { return value1.int_value > value2.int_value; } public static bool operator <(UserInt value1, UserInt value2) { return value1.int_value < value2.int_value; } public static bool operator >=(UserInt value1, UserInt value2) { return value1.int_value >= value2.int_value; } public static bool operator <=(UserInt value1, UserInt value2) { return value1.int_value <= value2.int_value; } public override bool isGreater(IUserDataType obj1) { if (!obj1.GetType().Equals(typeof(UserInt))) return false; return this > (obj1 as UserInt); } public override bool isSmaller(IUserDataType obj1) { if (!obj1.GetType().Equals(typeof(UserInt))) return false; return this < (obj1 as UserInt); } public override bool isEqual(IUserDataType obj1) { if (!obj1.GetType().Equals(typeof(UserInt))) return false; return this == (obj1 as UserInt); } public override bool isUnEqual(IUserDataType obj1) { if (!obj1.GetType().Equals(typeof(UserInt))) return false; return this != (obj1 as UserInt); } public override bool isMoreOrEqual(IUserDataType obj1) { if (!obj1.GetType().Equals(typeof(UserInt))) return false; return this >= (obj1 as UserInt); } public override bool isLessOrEqual(IUserDataType obj1) { if (!obj1.GetType().Equals(typeof(UserInt))) return false; return this <= (obj1 as UserInt); }}
这个userint类就是一个很普通的自定义类型,它重载了操作符号,并且这些重载过的操作符号被用于接口中的函数。
4.最重要的一个部分到了,自定义一个userString。
public class UserString : IConvertible, IUserDataType{ private string userData = ""; public UserString(string data) { userData = data; } public TypeCode GetTypeCode() { return TypeCode.Object; } public string Trim() { return userData.Trim(); } public string ToUpper() { return userData.ToUpper(); } public string SubString(int startindex) { return userData.Substring(startindex); } public string SubString(int startindex, int length) { return userData.Substring(startindex, length); } public static bool operator ==(UserString value1, UserString value2) { return value1.userData == value2.userData; } public static bool operator !=(UserString value1, UserString value2) { return value1.userData != value2.userData; } public bool ToBoolean(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public byte ToByte(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public char ToChar(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public DateTime ToDateTime(IFormatProvider provider) { return Convert.ToDateTime(this.userData); } public decimal ToDecimal(IFormatProvider provider) { return Convert.ToDecimal(this.userData); } public double ToDouble(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public short ToInt16(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public int ToInt32(IFormatProvider provider) { return Convert.ToInt32(this.userData); } public long ToInt64(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public sbyte ToSByte(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public float ToSingle(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public string ToString(IFormatProvider provider) { return this.userData; } public object ToType(Type conversionType, IFormatProvider provider) { switch (Type.GetTypeCode(conversionType)) { case TypeCode.Object: if (conversionType.IsAssignableFrom(typeof(UserInt))) return new UserInt(ToInt32(null)); else if (conversionType.IsAssignableFrom(typeof(UserDateTime))) return new UserDateTime(ToDateTime(null)); else if (conversionType.IsAssignableFrom(typeof(UserDecimal))) return new UserDecimal(ToDecimal(null)); else if (conversionType.IsAssignableFrom(typeof(UserString))) return new UserString(ToString(null)); else throw new InvalidCastException(String.Format("Conversion to a {0} is not supported.", conversionType.Name)); case TypeCode.Int32: return ToInt32(null); case TypeCode.Decimal: return ToDecimal(null); case TypeCode.DateTime: return ToDateTime(null); case TypeCode.String: return ToString(null); default: throw new InvalidCastException(String.Format("Conversion to {0} is not supported.", conversionType.Name)); } } public ushort ToUInt16(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public uint ToUInt32(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public ulong ToUInt64(IFormatProvider provider) { throw new Exception("The method or operation is not implemented."); } public bool isGreater(IUserDataType obj1) { return false; } public bool isSmaller(IUserDataType obj1) { return false; } public bool isEqual(IUserDataType obj1) { if (!obj1.GetType().Equals(typeof(UserString))) return false; return this == (obj1 as UserString); } public bool isUnEqual(IUserDataType obj1) { if (!obj1.GetType().Equals(typeof(UserString))) return false; return this != (obj1 as UserString); } public bool isMoreOrEqual(IUserDataType obj1) { return false; } public bool isLessOrEqual(IUserDataType obj1) { return false; }}
userString类继承自两个接口,分别是IConvertible和IUserDataType。
userString重要的原因是ToType函数,因为IConvertible在convert.changeType函数中实现的函数就是ToType。如果你能看懂这个ToType函数,那么基本上自定义类型转换的核心内容就了解完毕了。
好了,下面再说说具体实现,具体实现我只说说我的思路,具体代码需要你自己实现。不过别担心,我已经实现过了,这个思路是没问题的。
例子:
输入为:"int","23",">","int","32",这是一个典型的int类型的比较大小的操作。
1.根据"int"来生成一个Type,使用函数UserDataType.getType。
2.根据"23","32",使用UserString来生成两个UserString类型的对象,使用构造函数生成。
3.利用Convert.changeType来讲两个userString对象转换成userInt类型,changetype函数的两个参数分别为object和type,那么两个传入的传输分别为userstring对象和userint的type。
4.对操作符号进行枚举,比如此例子中操作符号为">",那么对应的IUserDataType的函数为isGreater,调用之后返回了false。
PS:我的英文水平很差,所以在函数定义命名方面不是很准确,见谅。此文的出现是为了记录我之前所做过的事情,以免以后忘记。
- C#通过IConvertible接口来实现自定义类型转换和计算
- 9.4.2 实现接口和类型转换
- IConvertible接口用法揭秘
- C# 实现农历计算和转换
- 通过实现接口来实现栈和队列
- C#中的自定义类型转换
- C#自定义类型强制转换
- 对象必须实现 IConvertible
- 通过反射来实现:DataTable 和List 相互转换
- 通过自定义类型计算大数阶乘
- c# 实现自定义事件访问器 和 实现接口事件
- 通过自定义的类来实现事件监听器接口的示例
- 解决“无法将System.Byte[]的对象强制转换为类型System.IConvertible”的错误
- C#学习- 通过基于接口的编程来实现数据库的切换
- 通过实现Runnable接口来创建线程
- 匿名内部类 通过接口来实现
- c#接口实现 - 第六节、接口转换
- C# 通过 Observer观察者 设计模式 来理解 抽象类 和 接口 应用在什么地方
- 互联网重心偏移于电子商务已成定论
- android 程序调试入门
- VC6.0代码升级到VS2010 (2)
- 互联网重心偏移于电子商务已成定论
- MD2格式简介
- C#通过IConvertible接口来实现自定义类型转换和计算
- Oracle查询数据表结构(字段,类型,大小,备注)
- VB.NET获取系统当前精确时间(毫秒级)
- 实用技巧:在Linux系统中查找文件的方法
- C# 数据库访问
- mysql 添加添加事务处理
- 进度对话框Progress Dialog的使用
- 导出excel 后 页面按钮失效(页面假死)
- Android调用天气预报的WebService简单例子