这个资源池用来管理程序的宝贵资源。
主要的类是ResourcePool<T>。
用户可以通过调用GetResource方法请求一个资源,用完之后通过ReturnResource归还给资源池。由资源池决定什么时候释放多余的资源。
接口IResourceProvider<T>用来获得资源。
类ResourceTag<T>用来标志资源是否在用。
主要的类是ResourcePool<T>。
用户可以通过调用GetResource方法请求一个资源,用完之后通过ReturnResource归还给资源池。由资源池决定什么时候释放多余的资源。
接口IResourceProvider<T>用来获得资源。
类ResourceTag<T>用来标志资源是否在用。
具体的就不多说了,请看代码。欢迎讨论。
先是测试代码:
1 using System;
2 using NUnit.Framework;
3 using System.Data.SqlClient;
4 public class SqlConnectionProvider: IResourceProvider<SqlConnection>
5 {
6 public SqlConnection Request()
7 {
8 SqlConnection con= new SqlConnection();
9 //在此打开数据库连接,因为ResourcePool要求管理那些能用的资源。
10 //con.Open();
11 return con;
12 }
13 public void Dispose(SqlConnection con)
14 {
15 //在此销毁对象
16 con.Dispose();
17 }
18 }
19 [TestFixture]
20 public class Test
21 {
22 [Test]
23 public void TestPool()
24 {
25 //此处初始化资源池,参数:一个资源提供类和一个最大资源池中最大资源数目
26 ResourcePool<SqlConnection> pool=ResourcePool<SqlConnection>.Instance(new SqlConnectionProvider(),10);
27
28 long resourceID;
29 SqlConnection con=pool.GetResource(out resourceID);
30 //在此处使用con对象
31
32 //用完就归还
33 pool.ReturnResource(ref con,resourceID);
34
35
36 }
37 }
2 using NUnit.Framework;
3 using System.Data.SqlClient;
4 public class SqlConnectionProvider: IResourceProvider<SqlConnection>
5 {
6 public SqlConnection Request()
7 {
8 SqlConnection con= new SqlConnection();
9 //在此打开数据库连接,因为ResourcePool要求管理那些能用的资源。
10 //con.Open();
11 return con;
12 }
13 public void Dispose(SqlConnection con)
14 {
15 //在此销毁对象
16 con.Dispose();
17 }
18 }
19 [TestFixture]
20 public class Test
21 {
22 [Test]
23 public void TestPool()
24 {
25 //此处初始化资源池,参数:一个资源提供类和一个最大资源池中最大资源数目
26 ResourcePool<SqlConnection> pool=ResourcePool<SqlConnection>.Instance(new SqlConnectionProvider(),10);
27
28 long resourceID;
29 SqlConnection con=pool.GetResource(out resourceID);
30 //在此处使用con对象
31
32 //用完就归还
33 pool.ReturnResource(ref con,resourceID);
34
35
36 }
37 }
(以上测试只是简单的演示功能,详细的测试代码跟项目其他类有关,贴上反而复杂。另:下面的实现也是经常改进,)
具体实现:
1 /// <summary>
2 /// 资源池,可以往里面加入资源,也可以取出来
3 /// </summary>
4 /// <typeparam name="T"></typeparam>
5 public class ResourcePool<T> : IDisposable where T : class, IDisposable
6 {
7 private static ResourcePool<T> pool;
8 IResourceProvider<T> resourceProvider;
9 private ResourcePool(IResourceProvider<T> resourceProvider)
10 {
11 this.resourceProvider = resourceProvider;
12 resources = new Dictionary<long,ResourceTag<T>> ();
13 }
14 public int ResourceCount
15 {
16 get
17 {
18 return resources.Keys.Count;
19 }
20 }
21
22 static object key3 = new object();
23 /// <summary>
24 /// 返回一个资源池,采用单件模式。
25 /// </summary>
26 /// <param name="resourceProvider"></param>
27 /// <returns></returns>
28 public static ResourcePool<T> Instance(IResourceProvider<T> resourceProvider)
29 {
30 if (pool == null)
31 {
32 lock (key3)
33 {
34 if (pool == null)
35 {
36 pool = new ResourcePool<T>(resourceProvider);
37 }
38 }
39 }
40 return pool;
41 }
42 Dictionary<long,ResourceTag<T>> resources;
43 /// <summary>
44 ///从资源池中提取资源
45 /// </summary>
46 /// <param name="resourID">向资源用户输出的resourceID,返回资源时用它来返回特定资源</param>
47 /// <returns></returns>
48 public T GetResource(out long resourID)
49 {
50 T result = null;
51 result = getFreeResource(out resourID);
52 return result;
53 }
54 object key1 = new object();
55 private T getFreeResource(out long resourID)
56 {
57 lock (key1)
58 {
59 foreach (long key in resources.Keys)
60 {
61 if (!resources[key].InUse)
62 {
63 resources[key].InUse = true;
64 resourID = key;
65 return resources[key].Resource;
66 }
67 }
68 //申请新资源
69 T res = resourceProvider.Request();
70 if (res == null)//申请资源失败
71 {
72 resourID = getNullResourceID();
73 return null;
74 }
75 else
76 {
77 ResourceTag<T> tag = new ResourceTag<T>(res, true);
78 long id = newResourceID();
79 resources.Add(id, tag);
80 resourID=id;
81 return res;
82 }
83 }
84 }
85
86 private long getNullResourceID()
87 {
88 return -1;
89 }
90 /// <summary>
91 /// 产生新的资源号
92 /// </summary>
93 /// <returns></returns>
94 private long newResourceID()
95 {
96 return DateTime.Now.Ticks;
97 }
98
99
100 /// <summary>
101 /// 返回资源
102 /// </summary>
103 /// <param name="resource">ref类型的参数,将在函数内部设为null,意味着返回后不能再用。</param>
104 /// <param name="resourceID">获取资源时得到的那个resourceID。如果返回一个不正确的id,将抛出异常。</param>
105 public void ReturnResource(ref T resource, long resourceID)
106 {
107 if (!resources.ContainsKey(resourceID))
108 {
109 throw new InvalidOperationException("试图归还一个非法的资源。");
110 }
111 returnRes(ref resource,resourceID);
112 }
113 object key2 = new object();
114 private void returnRes(ref T resource, long resourceID)
115 {
116 T toDispose = null;
117 lock (key2)
118 {
119 ResourceTag<T> tag = resources[resourceID];
120 tag.InUse = false;
121 resources.Remove(resourceID);//当前的id将作废,不能再用
122 resource = null;//将当前的resource置空,不能再用
123 if (resources.Keys.Count >=resourceProvider.MaxResource)//达到上限,将释放资源
124 {
125 toDispose = resource;
126 }
127 else
128 {
129 resources.Add(newResourceID(), tag);
130 }
131 }
132 if (toDispose != null)
133 {
134 resourceProvider.Dispose(toDispose);
135 }
136 }
137 #region IDisposable 成员 及 析构方法
138
139 public void Dispose()
140 {
141 Dispose(true);
142 }
143 ~ResourcePool()
144 {
145 Dispose(false);
146 }
147 public virtual void Dispose(bool isDisposing)
148 {
149 foreach (long key in resources.Keys)
150 {
151 resources[key].Resource.Dispose();//释放资源
152 }
153 if (isDisposing)
154 {
155 key1 = null;
156 key2 = null;
157 key3 = null;
158 resourceProvider = null;GC.SuppressFinalize()
159 }
160 }
161 #endregion
162
163 }
164 internal class ResourceTag<T>
165 {
166 private T resource;
167
168 internal T Resource
169 {
170 get { return resource; }
171 set { resource = value; }
172 }
173 private bool inUse;
174
175 internal bool InUse
176 {
177 get { return inUse; }
178 set { inUse = value; }
179 }
180 public ResourceTag(T resource, bool inUse)
181 {
182 Resource = resource;
183 InUse = inUse;
184 }
185
186 }
187 /// <summary>
188 /// 这个接口用来产生ResourcePool管理的资源,比如数据库连接对象等
189 /// </summary>
190 /// <typeparam name="T"></typeparam>
191 public interface IResourceProvider<T> where T : class, IDisposable
192 {
193 /// <summary>
194 /// 获得资源
195 /// </summary>
196 /// <returns>成功则返回资源对象,否则返回null</returns>
197 T Request();
198 void Dispose(T resource);
199 /// <summary>
200 /// 能提供的最大的资源数
201 /// </summary>
202 int MaxResource { get;}
203 }
2 /// 资源池,可以往里面加入资源,也可以取出来
3 /// </summary>
4 /// <typeparam name="T"></typeparam>
5 public class ResourcePool<T> : IDisposable where T : class, IDisposable
6 {
7 private static ResourcePool<T> pool;
8 IResourceProvider<T> resourceProvider;
9 private ResourcePool(IResourceProvider<T> resourceProvider)
10 {
11 this.resourceProvider = resourceProvider;
12 resources = new Dictionary<long,ResourceTag<T>> ();
13 }
14 public int ResourceCount
15 {
16 get
17 {
18 return resources.Keys.Count;
19 }
20 }
21
22 static object key3 = new object();
23 /// <summary>
24 /// 返回一个资源池,采用单件模式。
25 /// </summary>
26 /// <param name="resourceProvider"></param>
27 /// <returns></returns>
28 public static ResourcePool<T> Instance(IResourceProvider<T> resourceProvider)
29 {
30 if (pool == null)
31 {
32 lock (key3)
33 {
34 if (pool == null)
35 {
36 pool = new ResourcePool<T>(resourceProvider);
37 }
38 }
39 }
40 return pool;
41 }
42 Dictionary<long,ResourceTag<T>> resources;
43 /// <summary>
44 ///从资源池中提取资源
45 /// </summary>
46 /// <param name="resourID">向资源用户输出的resourceID,返回资源时用它来返回特定资源</param>
47 /// <returns></returns>
48 public T GetResource(out long resourID)
49 {
50 T result = null;
51 result = getFreeResource(out resourID);
52 return result;
53 }
54 object key1 = new object();
55 private T getFreeResource(out long resourID)
56 {
57 lock (key1)
58 {
59 foreach (long key in resources.Keys)
60 {
61 if (!resources[key].InUse)
62 {
63 resources[key].InUse = true;
64 resourID = key;
65 return resources[key].Resource;
66 }
67 }
68 //申请新资源
69 T res = resourceProvider.Request();
70 if (res == null)//申请资源失败
71 {
72 resourID = getNullResourceID();
73 return null;
74 }
75 else
76 {
77 ResourceTag<T> tag = new ResourceTag<T>(res, true);
78 long id = newResourceID();
79 resources.Add(id, tag);
80 resourID=id;
81 return res;
82 }
83 }
84 }
85
86 private long getNullResourceID()
87 {
88 return -1;
89 }
90 /// <summary>
91 /// 产生新的资源号
92 /// </summary>
93 /// <returns></returns>
94 private long newResourceID()
95 {
96 return DateTime.Now.Ticks;
97 }
98
99
100 /// <summary>
101 /// 返回资源
102 /// </summary>
103 /// <param name="resource">ref类型的参数,将在函数内部设为null,意味着返回后不能再用。</param>
104 /// <param name="resourceID">获取资源时得到的那个resourceID。如果返回一个不正确的id,将抛出异常。</param>
105 public void ReturnResource(ref T resource, long resourceID)
106 {
107 if (!resources.ContainsKey(resourceID))
108 {
109 throw new InvalidOperationException("试图归还一个非法的资源。");
110 }
111 returnRes(ref resource,resourceID);
112 }
113 object key2 = new object();
114 private void returnRes(ref T resource, long resourceID)
115 {
116 T toDispose = null;
117 lock (key2)
118 {
119 ResourceTag<T> tag = resources[resourceID];
120 tag.InUse = false;
121 resources.Remove(resourceID);//当前的id将作废,不能再用
122 resource = null;//将当前的resource置空,不能再用
123 if (resources.Keys.Count >=resourceProvider.MaxResource)//达到上限,将释放资源
124 {
125 toDispose = resource;
126 }
127 else
128 {
129 resources.Add(newResourceID(), tag);
130 }
131 }
132 if (toDispose != null)
133 {
134 resourceProvider.Dispose(toDispose);
135 }
136 }
137 #region IDisposable 成员 及 析构方法
138
139 public void Dispose()
140 {
141 Dispose(true);
142 }
143 ~ResourcePool()
144 {
145 Dispose(false);
146 }
147 public virtual void Dispose(bool isDisposing)
148 {
149 foreach (long key in resources.Keys)
150 {
151 resources[key].Resource.Dispose();//释放资源
152 }
153 if (isDisposing)
154 {
155 key1 = null;
156 key2 = null;
157 key3 = null;
158 resourceProvider = null;GC.SuppressFinalize()
159 }
160 }
161 #endregion
162
163 }
164 internal class ResourceTag<T>
165 {
166 private T resource;
167
168 internal T Resource
169 {
170 get { return resource; }
171 set { resource = value; }
172 }
173 private bool inUse;
174
175 internal bool InUse
176 {
177 get { return inUse; }
178 set { inUse = value; }
179 }
180 public ResourceTag(T resource, bool inUse)
181 {
182 Resource = resource;
183 InUse = inUse;
184 }
185
186 }
187 /// <summary>
188 /// 这个接口用来产生ResourcePool管理的资源,比如数据库连接对象等
189 /// </summary>
190 /// <typeparam name="T"></typeparam>
191 public interface IResourceProvider<T> where T : class, IDisposable
192 {
193 /// <summary>
194 /// 获得资源
195 /// </summary>
196 /// <returns>成功则返回资源对象,否则返回null</returns>
197 T Request();
198 void Dispose(T resource);
199 /// <summary>
200 /// 能提供的最大的资源数
201 /// </summary>
202 int MaxResource { get;}
203 }