通用对象池
Generic object pool
是否可以创建一个在其中创建新对象的通用对象池?
另外,如果这个对象创建可以接收参数就好了。
public interface IPoolable
{
void Dispose();
}
public class ObjectPool<T> where T : IPoolable
{
private List<T> pool;
public T Get()
{
if(pool.count > 0)
{
return pool.Pop();
}
else
{
return new T(); // <- How to do this properly?
}
}
}
public class SomeClass : IPoolable
{
int id;
public SomeClass(int id)
{
this.id = id;
}
public void Dispose()
{
}
}
public class OtherClass : IPoolable
{
string name;
int id;
public OtherClass(string name, int id)
{
this.name = name;
this.id = id;
}
public void Dispose()
{
}
}
如果能接收参数就可以这样使用
SomeClass a = myPool.Get(2);
OtherClass b = myOtherPool.Get("foo", 4);
或者没有参数也可以。
SomeClass a = myPool.Get();
a.id = 2;
OtherClass b = myOtherPool.Get();
b.name = "foo";
b.id = 4;
您可以使用 Activator.CreateInstance
Method
public static object CreateInstance(
Type type,
params object[] args
)
像这样
return (T)Activator.CreateInstance(typeof(T), id);
但是,没有办法指定类型必须为构造函数提供参数;既不在接口声明中,也不在泛型类型约束中,也不在 class 继承中。
你可以这样做:
public class ObjectPool<T>
{
private Queue<T> _pool = new Queue<T>();
private const int _maxObjects = 100; // Set this to whatever
public T Get(params object[] parameters)
{
T obj;
if (_pool.Count < 1)
obj = (T)Activator.CreateInstance(typeof(T), parameters);
else
obj = _pool.Dequeue();
return obj;
}
public void Put(T obj)
{
if (_pool.Count < _maxObjects)
_pool.Enqueue(obj);
}
}
我正在寻找类似的东西并遇到了这个:
public class ObjectPool<TObject>
{
private int maxPoolSize;
private SpinLock poolLock;
private Dictionary<Type, Stack<TObject>> poolCache;
private Func<TObject> factory;
public ObjectPool(int poolSize)
{
this.maxPoolSize = poolSize;
this.poolLock = new SpinLock(false);
this.poolCache = new Dictionary<Type, Stack<TObject>>();
}
public ObjectPool(int poolSize, Func<TObject> factory) : this(poolSize)
{
this.factory = factory;
}
public T Rent<T>() where T : TObject
=> (T)this.Rent(typeof(T));
public TObject Rent(Type type)
{
bool lockTaken = false;
Stack<TObject> cachedCollection;
this.poolLock.Enter(ref lockTaken);
try
{
if (!this.poolCache.TryGetValue(type, out cachedCollection))
{
cachedCollection = new Stack<TObject>();
this.poolCache.Add(type, cachedCollection);
}
}
finally
{
if (lockTaken)
{
this.poolLock.Exit(false);
}
}
if (cachedCollection.Count > 0)
{
TObject instance = cachedCollection.Pop();
if (instance != null)
return instance;
}
// New instances don't need to be prepared for re-use, so we just return it.
if (this.factory == null)
{
return (TObject)Activator.CreateInstance(type);
}
else
{
return this.factory();
}
}
public void Return(TObject instanceObject)
{
Stack<TObject> cachedCollection = null;
Type type = typeof(TObject);
bool lockTaken = false;
this.poolLock.Enter(ref lockTaken);
try
{
if (!this.poolCache.TryGetValue(type, out cachedCollection))
{
cachedCollection = new Stack<TObject>();
this.poolCache.Add(type, cachedCollection);
}
if (cachedCollection.Count >= this.maxPoolSize)
{
return;
}
cachedCollection.Push(instanceObject);
}
finally
{
if (lockTaken)
{
this.poolLock.Exit(false);
}
}
}
}
这是一个非常好的实现,我无耻地从 here
那里偷走了
它支持池化任何继承自泛型类型参数的对象。
是否可以创建一个在其中创建新对象的通用对象池? 另外,如果这个对象创建可以接收参数就好了。
public interface IPoolable
{
void Dispose();
}
public class ObjectPool<T> where T : IPoolable
{
private List<T> pool;
public T Get()
{
if(pool.count > 0)
{
return pool.Pop();
}
else
{
return new T(); // <- How to do this properly?
}
}
}
public class SomeClass : IPoolable
{
int id;
public SomeClass(int id)
{
this.id = id;
}
public void Dispose()
{
}
}
public class OtherClass : IPoolable
{
string name;
int id;
public OtherClass(string name, int id)
{
this.name = name;
this.id = id;
}
public void Dispose()
{
}
}
如果能接收参数就可以这样使用
SomeClass a = myPool.Get(2);
OtherClass b = myOtherPool.Get("foo", 4);
或者没有参数也可以。
SomeClass a = myPool.Get();
a.id = 2;
OtherClass b = myOtherPool.Get();
b.name = "foo";
b.id = 4;
您可以使用 Activator.CreateInstance
Method
public static object CreateInstance(
Type type,
params object[] args
)
像这样
return (T)Activator.CreateInstance(typeof(T), id);
但是,没有办法指定类型必须为构造函数提供参数;既不在接口声明中,也不在泛型类型约束中,也不在 class 继承中。
你可以这样做:
public class ObjectPool<T>
{
private Queue<T> _pool = new Queue<T>();
private const int _maxObjects = 100; // Set this to whatever
public T Get(params object[] parameters)
{
T obj;
if (_pool.Count < 1)
obj = (T)Activator.CreateInstance(typeof(T), parameters);
else
obj = _pool.Dequeue();
return obj;
}
public void Put(T obj)
{
if (_pool.Count < _maxObjects)
_pool.Enqueue(obj);
}
}
我正在寻找类似的东西并遇到了这个:
public class ObjectPool<TObject>
{
private int maxPoolSize;
private SpinLock poolLock;
private Dictionary<Type, Stack<TObject>> poolCache;
private Func<TObject> factory;
public ObjectPool(int poolSize)
{
this.maxPoolSize = poolSize;
this.poolLock = new SpinLock(false);
this.poolCache = new Dictionary<Type, Stack<TObject>>();
}
public ObjectPool(int poolSize, Func<TObject> factory) : this(poolSize)
{
this.factory = factory;
}
public T Rent<T>() where T : TObject
=> (T)this.Rent(typeof(T));
public TObject Rent(Type type)
{
bool lockTaken = false;
Stack<TObject> cachedCollection;
this.poolLock.Enter(ref lockTaken);
try
{
if (!this.poolCache.TryGetValue(type, out cachedCollection))
{
cachedCollection = new Stack<TObject>();
this.poolCache.Add(type, cachedCollection);
}
}
finally
{
if (lockTaken)
{
this.poolLock.Exit(false);
}
}
if (cachedCollection.Count > 0)
{
TObject instance = cachedCollection.Pop();
if (instance != null)
return instance;
}
// New instances don't need to be prepared for re-use, so we just return it.
if (this.factory == null)
{
return (TObject)Activator.CreateInstance(type);
}
else
{
return this.factory();
}
}
public void Return(TObject instanceObject)
{
Stack<TObject> cachedCollection = null;
Type type = typeof(TObject);
bool lockTaken = false;
this.poolLock.Enter(ref lockTaken);
try
{
if (!this.poolCache.TryGetValue(type, out cachedCollection))
{
cachedCollection = new Stack<TObject>();
this.poolCache.Add(type, cachedCollection);
}
if (cachedCollection.Count >= this.maxPoolSize)
{
return;
}
cachedCollection.Push(instanceObject);
}
finally
{
if (lockTaken)
{
this.poolLock.Exit(false);
}
}
}
}
这是一个非常好的实现,我无耻地从 here
那里偷走了它支持池化任何继承自泛型类型参数的对象。