Unity IoC - ComponentCreated / OnActivating / RegisterInitializer 事件

Unity IoC - ComponentCreated / OnActivating / RegisterInitializer events

我正在使用 Microsoft Unity IOC 容器,我希望能够在每次创建(未注册)组件时引发事件,即生命周期事件

例如

Unity 中的等价物是什么?

开箱即用的 Unity 没有通知。但是,Unity 提供了使用 UnityContainerExtension 扩展容器功能的能力,这让您可以相当轻松地添加通知。

容器可以在多个阶段通过指定 UnityBuildStage 的哪一部分扩展到 运行 来连接到构建管道(阶段是设置、类型映射、生命周期, PreCreation, Creation, Initialization, PostInitialization)。 (这可能会有点棘手,因为管道可能会短路,就像使用 'singleton' ContainerControlledLifetimeManager 管道在生命周期停止的情况一样。)

在容器扩展中已经有两个通知注册的事件:RegisteringRegisteringInstance。如果您关心注册,这些可能会有用。

如果你想在对象被解析或拆除时收到通知,那么你可以编写一个类似于这样的容器扩展:

public class BuildNotificationExtension : UnityContainerExtension
{
    public event EventHandler<NamedTypeBuildKey> BuiltUp;
    public event EventHandler<object> TearDown;

    protected override void Initialize()
    {
        var builderAwareStrategy = new CustomBuilderAwareStrategy(this.BuiltUp, this.TearDown);
        // Run before Lifetime so we know about all resolved calls
        // even if singleton that is not actually built up
        base.Context.Strategies.Add(builderAwareStrategy, UnityBuildStage.TypeMapping);
    }

    private class CustomBuilderAwareStrategy : BuilderStrategy
    {
        private event EventHandler<NamedTypeBuildKey> BuiltUp;
        private event EventHandler<object> TearDown;

        public CustomBuilderAwareStrategy(EventHandler<NamedTypeBuildKey> builtUp,
            EventHandler<object> tearDown)
        {
            this.BuiltUp = builtUp;
            this.TearDown = tearDown;
        }

        public override void PreBuildUp(IBuilderContext context)
        {
            this.BuiltUp?.Invoke(this, context.BuildKey);
        }

        public override void PreTearDown(IBuilderContext context)
        {
            this.TearDown?.Invoke(this, context.Existing);
        }
    }
}

如果您 运行 这个控制台应用程序:

class Program
{
    private class Foo {}
    private interface ILogger { }

    private class Logger : ILogger
    {
        public Logger(Foo foo1,  Foo foo2) { }
    }

    static void Main(string[] args)
    {
        var buildNotificationExtension = new BuildNotificationExtension();
        buildNotificationExtension.BuiltUp += (sender, key) =>
        {
            Console.WriteLine($"Built up type '{key.Type.Name}' with name '{key.Name}'.");
        };
        buildNotificationExtension.TearDown += (sender, obj) =>
        {
            Console.WriteLine($"Tear down type '{obj.GetType().Name}'.");
        };

        IUnityContainer container = new UnityContainer()
            .AddExtension(buildNotificationExtension)
            // Register ILogger as singleton
            .RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager());

        var logger = container.Resolve<ILogger>();
        var anotherLogger = container.Resolve<ILogger>();

        container.Teardown(logger);
    }
}

您将收到以下输出:

Built up type 'Logger' with name ''.
Built up type 'Foo' with name ''.
Built up type 'Foo' with name ''.
Built up type 'Logger' with name ''.
Tear down type 'Logger'.

显示第一个 Logger 已解决,导致两个 Foo 实例被解决。然后 Logger 再次解析,但由于它是单例,因此返回当前 Logger 实例并且没有实例化新的 Foo 实例。最后Logger被拆了

此方法可用于向 Unity 处理管道的不同阶段添加额外的通知。例如您可以修改 BuildNotificationExtension class 以接受多个阶段并向每个阶段添加通知。