Unity 4.0.1:如何检索容器已实例化的所有对象?
在Unity 4.0.1中检索容器实例化的对象
嘿,刚好我之前也研究过这个问题——Unity 4.0.1本身并没有提供像你想要的GetAllInstantiatedObjects()这样的内置API来直接获取容器已经创建的所有实例。不过我们可以通过扩展Unity的容器功能来实现这个需求,下面给你两种可行的方案:
方案一:自定义容器扩展,跟踪所有实例
这个方法会创建一个容器扩展,在每个对象被容器实例化完成后自动记录下来,支持按类型筛选。
首先创建跟踪扩展类:
using System.Collections.Generic; using System.Linq; using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.ObjectBuilder; public class InstanceTrackingExtension : ContainerExtension { private readonly List<object> _trackedInstances = new List<object>(); // 获取所有被跟踪的实例 public IEnumerable<object> AllInstantiatedObjects => _trackedInstances.AsReadOnly(); // 获取指定类型的实例 public IEnumerable<T> GetAllInstantiatedObjects<T>() { return _trackedInstances.OfType<T>(); } protected override void Initialize() { // 添加一个构建策略,在对象初始化完成后记录实例 Context.Strategies.Add(new InstanceTrackingStrategy(_trackedInstances), UnityBuildStage.PostInitialization); } private class InstanceTrackingStrategy : BuilderStrategy { private readonly List<object> _instanceList; public InstanceTrackingStrategy(List<object> instanceList) { _instanceList = instanceList; } public override void PostBuildUp(IBuilderContext context) { var createdInstance = context.Existing; if (createdInstance != null && !_instanceList.Contains(createdInstance)) { _instanceList.Add(createdInstance); } } } }
使用方式
把这个扩展添加到你的容器中,之后所有通过容器Resolve或依赖注入创建的对象都会被自动跟踪:
var unityContainer = new UnityContainer(); var trackingExtension = new InstanceTrackingExtension(); unityContainer.AddExtension(trackingExtension); // 注册并创建实例 unityContainer.RegisterType<IFoo, Foo>(); var foo1 = unityContainer.Resolve<IFoo>(); var foo2 = unityContainer.Resolve<IFoo>(); var bar = unityContainer.Resolve<Bar>(); // 获取所有实例 IEnumerable<object> allInstances = trackingExtension.AllInstantiatedObjects; // 获取所有IFoo类型的实例 IEnumerable<IFoo> instantiatedFoos = trackingExtension.GetAllInstantiatedObjects<IFoo>();
⚠️ 注意事项:
- 这个方案会持有所有实例的引用,瞬态对象会因为被跟踪列表引用而无法被GC回收,如果你需要管理内存,记得在对象不再使用时手动从
_trackedInstances中移除,或者只跟踪特定生命周期的对象(比如单例)。 - 仅跟踪通过当前容器创建的对象,手动
new的对象不会被记录;如果使用子容器,需要给子容器单独添加这个扩展。
方案二:仅检索单例实例
如果你只关心单例对象,Unity提供了Registrations属性可以获取所有注册信息,我们可以从中筛选出单例注册并获取实例:
using System.Collections.Generic; using System.Linq; using Microsoft.Practices.Unity; public static class UnityContainerExtensions { public static IEnumerable<T> GetAllSingletonInstances<T>(this IUnityContainer container) { return container.Registrations // 筛选出单例生命周期的注册 .Where(reg => reg.LifetimeManager is SingletonLifetimeManager) // 解析获取实例 .Select(reg => container.Resolve(reg.RegisteredType)) // 转换为指定类型 .OfType<T>(); } }
使用时直接调用扩展方法即可:
IEnumerable<IFoo> singletonFoos = unityContainer.GetAllSingletonInstances<IFoo>();
这个方法不会持有额外引用,不会影响GC,但只能获取单例对象,瞬态对象无法通过这种方式检索。
内容的提问来源于stack exchange,提问作者MattBecker82
相关产品推荐
相关产品推荐

