用C#建立通用对象池[2]

 

创建一个接口,用于限定对象池中所保存的对象的基本行为:

 

   

    public interface IDynamicObject

    {

       void Create(Object param);

       Object GetInnerObject();

       bool IsValidate();

       void Release();

    }

 

 

我们在对象池中存放的对象,必须继承上面的接口,并实现接口定义的每一个方法。

Create方法中,用户可以用来创建实际的对象,如建立数据库连接,并打开这个连接;GetInnerObject方法,使用户可以返回这个实际的对象,如一个SqlConnection对象;IsValidate方法是用来判断用户自定义对象的有效性的,是对象池决定是否重新创建对象的标志;Release方法中,用户可以进行资源释放工作。

 

有了上面的接口定义,为我们可以在列表中保存用户自定义对象打下了基础。下面就是要实现这个ObjectPool了。

用户自定义对象在我们的ObjectPool中,可以用列表存储,如ArrayList或者Hashtable,为了表示每个用户对象的状态,我们还需要将用户自定义对象包装一下,然后在放到列表中保存。下面定义了一个ObjectPool类的子类,用于包装用户自定义对象:

 

 

   

       private class PoolItem

       {

           private IDynamicObject _object;

           private bool  _bUsing;

           private Type _type;

           private Object _CreateParam;

 

           public PoolItem(Type type,Object param)

           {

              _type = type;

              _CreateParam = param;

              Create();

           }

 

           private void Create()

           {

              _bUsing = false;

 

              _object = (IDynamicObject)System.Activator.CreateInstance(_type);

              _object.Create(_CreateParam);

 

           }

           public void Recreate()

           {

              _object.Release();

              Create();

           }

           public void Release()

           {

              _object.Release();

           }

           public Object InnerObject

           {

              get{return _object.GetInnerObject();}

           }

           public int InnerObjectHashcode

           {

              get{return InnerObject.GetHashCode();}

           }

           public bool IsValidate

           {

              get{return _object.IsValidate();}

           }

           public bool Using

           {

              get{return _bUsing;}

              set

              {

                  _bUsing = value;

              }

           }

       }// class PoolItem

 

 

这个类,一个关键的属性是Using,该属性表示对象是否正在被被用户使用。注意,PoolItem创建时,接受一个Object类型的Param参数,这个参数最后被传递给用户自定义对象的Create方法。用户可以利用这一点,在创建ObjectPool时指定一些参数,供其自定义对象在创建时使用。比如创建SocketPool时,将服务器IP,端口通过Param传递给自定义对象的Create方法,用户就可以在Create方法中连接指定的服务器了。

以下是ObjectPool的具体实现代码:

 

 

   

    public sealed class ObjectPool

    {

       private Int32 _nCapacity;

       private Int32 _nCurrentSize;

       private Hashtable _listObjects;                                    private ArrayList _listFreeIndex;

       private ArrayList _listUsingIndex;

       private Type _typeObject;

       private Object _objCreateParam;

 

       public ObjectPool(Type type, Object create_param, Int32 init_size, Int32 capacity)

       {

           if(init_size < 0 || capacity < 1 || init_size>capacity)

           {

              throw(new Exception("Invalid parameter!"));

           }

 

           _nCapacity = capacity;

           _listObjects = new Hashtable(capacity);

           _listFreeIndex = new ArrayList(capacity);

           _listUsingIndex = new ArrayList(capacity);

           _typeObject = type;

           _objCreateParam = create_param;

 

           for(int i=0;i<init_size;i++)

           {

              PoolItem pitem = new PoolItem(type,create_param);

              _listObjects.Add(pitem.InnerObjectHashcode,pitem);

              _listFreeIndex.Add(pitem.InnerObjectHashcode);

           }

 

           _nCurrentSize = _listObjects.Count;

       }

 

       public void Release()

       {

           lock(this)

           {

              foreach(DictionaryEntry de in _listObjects)

              {

                  ( (PoolItem)de.Value ).Release();

              }

              _listObjects.Clear();

              _listFreeIndex.Clear();

              _listUsingIndex.Clear();

           }

       }

 

       public Int32 CurrentSize

       {

           get{return _nCurrentSize;}

       }

 

       public Int32 ActiveCount

       {

           get{return _listUsingIndex.Count;}

       }

 

       public Object GetOne()

       {

           lock(this)

           {

              if(_listFreeIndex.Count == 0)  

              {

                  if(_nCurrentSize == _nCapacity)

                  {

                     return null;

                  }

 

                  PoolItem pnewitem = new PoolItem(_typeObject,_objCreateParam);

                  _listObjects.Add(pnewitem.InnerObjectHashcode,pnewitem);

                  _listFreeIndex.Add(pnewitem.InnerObjectHashcode);

                  _nCurrentSize++;

              }

 

              Int32 nFreeIndex = (Int32)_listFreeIndex[0];    

              PoolItem pitem = (PoolItem)_listObjects[nFreeIndex];

              _listFreeIndex.RemoveAt(0);

              _listUsingIndex.Add(nFreeIndex);

             

              if(!pitem.IsValidate)

              {

                  pitem.Recreate();

              }

              pitem.Using = true;

 

              return pitem.InnerObject;

           }

       }

 

       public void FreeObject(Object obj)

       {

           lock(this)

           {

              int key = obj.GetHashCode();

              if(_listObjects.ContainsKey(key))

              {

                  PoolItem item = (PoolItem)_listObjects[key];

                  item.Using = false;

                  _listUsingIndex.Remove(key);

                  _listFreeIndex.Add(key);

              }

           }

       }

 

       public Int32 DecreaseSize(Int32 size)

       {

           Int32 nDecrease = size;

           lock(this)

           {

              if(nDecrease <= 0)

              {

                  return 0;

              }

              if(nDecrease > _listFreeIndex.Count)

              {

                  nDecrease = _listFreeIndex.Count;

              }

              for(int i=0;i<nDecrease;i++)

              {

                  _listObjects.Remove(_listFreeIndex[i]);

              }

 

              _listFreeIndex.Clear();

              _listUsingIndex.Clear();

 

              foreach(DictionaryEntry de in _listObjects)

              {

                  PoolItem pitem = (PoolItem)de.Value;

                  if(pitem.Using)

                  {

                     _listUsingIndex.Add(pitem.InnerObjectHashcode);

                  }

                  else

                  {

                     _listFreeIndex.Add(pitem.InnerObjectHashcode);

                  }

              }

 

           }

           _nCurrentSize -= nDecrease;

           return nDecrease;

       }

    }

 

 

 

下篇再给出一个用这个ObjectPool实现的数据库连接池的例子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值