今天跟大家分享一下如何封装自己的接口和类。
首先我们看一下封装自己的接口:
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接口中我们自己定义的几个方法即可。
我们看到,我们自己定义在接口里的方法都实现了,当然在类中可以增加自己的方法,但是必须要实现被继承接口的方法。