今天跟大家分享一下如何封装自己的接口和类。
首先我们看一下封装自己的接口:
IDictionary是键/值对的泛型集合的基接口,每个元素都是存在keyValuepair对象中的键值对。这个大家应该 比价熟悉。因为在.net开发中我们经常会用到键/值对。每一对都必须有唯一的键。
微软帮助文档中 IDictionary<Tkey,Tvalue>在命名空间: System.Collections.Generic,程序集: mscorlib(在 mscorlib.dll 中)。
这个接口继承了多个接口
public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
大家可以看到,Idictionary继承了Icollection,Ienumerable等。那么我们今天分享的是,我们自己写一个接口,来继承Idictionary接口。
1 /// <summary> 2 /// 哈希对象 3 /// </summary> 4 public interface IHashObject : IDictionary<string, object> 5 { 6 /// <summary> 7 /// 克隆 8 /// </summary> 9 /// <returns></returns> 10 IHashObject Clone(); 11 12 /// <summary> 13 /// 添加多个项 14 /// </summary> 15 /// <param name="keys"></param> 16 /// <param name="values"></param> 17 void Add(string[] keys, params object[] values); 18 /// <summary> 19 /// 拷贝所有数据到另一个实例 20 /// </summary> 21 /// <param name="dict"></param> 22 void CopyTo(IDictionary<string, object> dict); 23 24 /// <summary> 25 /// 取指定的值,默认值为null或0或false或空字符串 26 /// </summary> 27 /// <typeparam name="T"></typeparam> 28 /// <param name="key"></param> 29 /// <returns></returns> 30 T GetValue<T>(string key); 31 32 /// <summary> 33 /// 取指定的值,找不到则返回默认值 34 /// </summary> 35 /// <typeparam name="T"></typeparam> 36 /// <param name="key"></param> 37 /// <param name="defaultValue">默认值</param> 38 /// <returns></returns> 39 T GetValue<T>(string key, T defaultValue); 40 41 /// <summary> 42 /// key存在则保持已有值不变返回false;不存在则设置并返回 true 43 /// </summary> 44 /// <param name="key"></param> 45 /// <param name="value"></param> 46 /// <returns></returns> 47 bool CheckSetValue(string key, object value); 48 }
看上面的代码,我们自己定义了一个接口IHashObject接口继承Idictionary<string,object>的接口,这也就意味着,IHashObject继承了Idictionary继承的所有接口(Icollection,Ienumerable等)。
当然仅仅写一个接口继承其他接口,是没有任何意义的。然后在我们自己定义的接口中增加我们自己定义的方法,才有意义。
我们这里定义了一下几个自己的方法:
IHashObject Clone();
添加多个项
void Add(string[] keys, params object[] values);
贝所有数据到另一个实例
void CopyTo(IDictionary<string, object> dict);
取指定的值,默认值为null或0或false或空字符串
T GetValue<T>(string key);
取指定的值,找不到则返回默认值
T GetValue<T>(string key, T defaultValue);
key存在则保持已有值不变返回false;不存在则设置并返回 true
bool CheckSetValue(string key, object value);
当然在接口中定义的方法只是一个规范,不能实现它,要实现该接口必须要在继承该接口的类里面去实现。下面我们就去看一看怎样去实现接口。
1 /// <summary> 2 /// 哈希对象 3 /// </summary> 4 [Serializable] 5 public class HashObject : Dictionary<string, object>, IHashObject 6 { 7 /// <summary> 8 /// 默认 9 /// </summary> 10 public HashObject() 11 : base() 12 { 13 } 14 15 /// <summary> 16 /// 从已有数据复制 17 /// </summary> 18 /// <param name="dictionary"></param> 19 public HashObject(IDictionary<string, object> dictionary) 20 : base(dictionary) 21 { 22 } 23 24 /// <summary> 25 /// 序列化构建函数,必须有这个函数才能反序列化 26 /// </summary> 27 /// <param name="info"></param> 28 /// <param name="context"></param> 29 protected HashObject(SerializationInfo info, StreamingContext context) 30 : base(info, context) 31 { 32 } 33 34 /// <summary> 35 /// 传入许多键和值 36 /// </summary> 37 /// <param name="keys"></param> 38 /// <param name="values"></param> 39 public HashObject(string[] keys, params object[] values) 40 { 41 InternalAdd(this, keys, values); 42 } 43 44 /// <summary> 45 /// 克隆 46 /// </summary> 47 /// <returns></returns> 48 public IHashObject Clone() 49 { 50 HashObject clone = new HashObject(); 51 foreach (KeyValuePair<string, object> pair in this) 52 { 53 clone.Add(pair.Key, pair.Value); 54 } 55 return clone; 56 } 57 58 /// <summary> 59 /// 添加条目 60 /// </summary> 61 /// <param name="keys"></param> 62 /// <param name="values"></param> 63 public void Add(string[] keys, params object[] values) 64 { 65 InternalAdd(this, keys, values); 66 } 67 68 /// <summary> 69 /// 存取值 70 /// </summary> 71 /// <param name="key"></param> 72 /// <returns></returns> 73 public new object this[string key] 74 { 75 get 76 { 77 try 78 { 79 return base[key]; 80 } 81 catch (KeyNotFoundException) 82 { 83 throw new KeyNotFoundException(string.Format("关键字“{0}”不在HashObject中。", key)); 84 } 85 } 86 set 87 { 88 base[key] = value; 89 } 90 } 91 92 public bool CheckSetValue(string key, object value) 93 { 94 if (this.ContainsKey(key)) 95 { 96 return false; 97 } 98 this[key] = value; 99 return true; 100 } 101 102 /// <summary> 103 /// 重写只是为了避免警告 104 /// </summary> 105 /// <returns></returns> 106 public override int GetHashCode() 107 { 108 return base.GetHashCode(); 109 } 110 111 /// <summary> 112 /// 是否相等 113 /// </summary> 114 /// <param name="obj"></param> 115 /// <returns></returns> 116 public override bool Equals(object obj) 117 { 118 if (obj == null) 119 return false; 120 if (!(obj is HashObject)) 121 return false; 122 123 HashObject that = (HashObject)obj; 124 if (this.Count != that.Count) 125 return false; 126 foreach (string name in this.Keys) 127 { 128 if (!that.ContainsKey(name)) 129 return false; 130 object aValue = this[name]; 131 object bValue = that[name]; 132 if ((aValue != null) || (bValue != null)) 133 { 134 if (!object.Equals(this[name], that[name])) 135 return false; 136 } 137 } 138 139 return true; 140 } 141 142 private static void InternalAdd(HashObject obj, string[] keys, object[] values) 143 { 144 if (keys.Length != values.Length) 145 throw new InvalidOperationException("Keys和Values的长度不一致!"); 146 if (keys.Length == 0) 147 throw new InvalidOperationException("添加数据必须有一项!"); 148 149 for (int i = 0; i < keys.Length; i++) 150 { 151 obj.Add(keys[i], values[i]); 152 } 153 } 154 155 /// <summary> 156 /// 拷贝所有项到 157 /// </summary> 158 /// <param name="dict"></param> 159 public void CopyTo(IDictionary<string, object> dict) 160 { 161 foreach (KeyValuePair<string, object> pair in this) 162 { 163 dict[pair.Key] = pair.Value; 164 } 165 } 166 /// <summary> 167 /// 取指定的值,默认值为null或0或false 168 /// </summary> 169 /// <typeparam name="T"></typeparam> 170 /// <param name="key"></param> 171 /// <returns></returns> 172 public T GetValue<T>(string key) 173 { 174 return GetValue<T>(key, default(T)); 175 } 176 177 /// <summary> 178 /// 取指定的值,找不到则返回默认值 179 /// </summary> 180 /// <typeparam name="T"></typeparam> 181 /// <param name="key"></param> 182 /// <param name="defaultValue"></param> 183 /// <returns></returns> 184 public T GetValue<T>(string key, T defaultValue) 185 { 186 object value; 187 if (this.TryGetValue(key, out value)) 188 { 189 Type type = typeof(T); 190 Type underlyingType = type; 191 if (value == DBNull.Value) 192 { 193 return defaultValue; 194 } 195 else if (value != null && ReflectionUtils.IsPrimitiveType(type, out underlyingType)) 196 { 197 return (T)ChangeType(value, underlyingType); 198 } 199 else if (value != null && underlyingType != type && 200 underlyingType.IsEnum && !value.GetType().IsEnum) // 整数转成 Nullable<enum> 201 { 202 return (T)Enum.ToObject(underlyingType, value); 203 } 204 else if (value == null && underlyingType.IsSubclassOf(typeof(ValueType))) 205 { 206 return defaultValue; // null转成ulong 207 } 208 else // 只能强转,可能出错 209 { 210 return (T)value; 211 } 212 } 213 else 214 { 215 return defaultValue; 216 } 217 } 218 219 internal static object ChangeType(object value, Type type) 220 { 221 if (type == typeof(bool) && value.GetType() == typeof(string)) 222 { 223 return (string)value == "1"; 224 } 225 return Convert.ChangeType(value, type, null); 226 } 227 }
首先我们定义了一个类HashObject,继承了Dictionary<string, object>, IHashObject。为什么要继承Dictionary<string, object>呢?我想大家都知道,Dictionary类是
是IDictionary的实现类,如果我们不继承这个类,我们必须去实现IDictionary自身定义的方法,甚至可能去实现IDictionary所继承的接口的方法。只要我们继承Dictionary这个类,我们就不用去实现被继承接口的方法。
然后继承了我们刚刚自己写的IHashObject,我们只需要实现IHashObject接口中我们自己定义的几个方法即可。
我们看到,我们自己定义在接口里的方法都实现了,当然在类中可以增加自己的方法,但是必须要实现被继承接口的方法。
----------新手,语言组织,和理论知识不强,谢谢谅解。