減少頻繁創建/銷燬對象開銷,且限制最大活躍實例數(如資源密集型服務),防止資源耗盡。
public sealed class InstancePoolResolver {
private static readonly Dictionary _typeMap = new();
private static readonly Dictionary _maxCount = new();
private static readonly Dictionary> _pools = new();
private static readonly object _lock = new();
public static void Register() where TProvider : class, new() {
var iface = typeof(T);
lock (_lock) {
if (_typeMap.ContainsKey(iface)) throw new Exception("已註冊");
_typeMap[iface] = typeof(TProvider);
_pools[iface] = new List();
var attr = typeof(TProvider).GetCustomAttributes(typeof(InstanceSettingAttribute), false).FirstOrDefault() as InstanceSettingAttribute;
_maxCount[iface] = attr?.MaxInstanceGlobal ?? 10;
}
}
public static T Resolve() where T : PoolableObject {
var iface = typeof(T);
lock (_lock) {
var pool = _pools[iface];
// 1. 尋找閒置對象
foreach (var obj in pool)
if (obj.IsInPool) { obj.IsInPool = false; return (T)obj; }
// 2. 未達上限,創建新對象
if (pool.Count < _maxCount[iface]) {
var obj = (PoolableObject)Activator.CreateInstance(_typeMap[iface]);
pool.Add(obj);
obj.IsInPool = false;
return (T)obj;
}
// 3. 池滿,拋異常
throw new Exception("Object Pool fulled!");
}
}
}
[AttributeUsage(AttributeTargets.Class)]
public class InstanceSettingAttribute : Attribute {
public int MaxInstanceGlobal { get; set; } = 10;
}
public abstract class PoolableObject : IDisposable {
public bool IsInPool { get; set; } = true;
public void Dispose() => IsInPool = true; // 歸還池中
}
[InstanceSetting(MaxInstanceGlobal = 2)]
public class OrderQueryService : OrderQueryServiceInterface { /* ... */ }
// 註冊
InstancePoolResolver.Register();
// 多線程消費
Parallel.For(0, 20, _ => {
using (var svc = InstancePoolResolver.Resolve()) {
Console.WriteLine($"Object ID: {svc.GetHashCode()}");
Thread.Sleep(1000); // 模擬長時間佔用
}
});
運行結果:同時只有 2 個實例被複用,超出拋異常。
using 區塊自動調用 Dispose() 歸還對象