如何在组件被处置之前运行一段代码?

发布于 2024-12-27 09:40:52 字数 3990 浏览 1 评论 0原文

我正在使用 castle-windsor 框架,并且我想在框架发布特定(第三方)组件之前调用一段代码。

我认为可以通过向 OnDestroy 添加委托来实现此目的,但框架始终首先调用 Dispose。 (参见下面的示例)。

在调用 Dispose 之前,我必须使用哪些选项来调用代码?

public class TestClass : IDisposable
{
    static long _globalInstanceCount = 0;
    readonly long _instanceId;
    public TestClass()
    {
        _instanceId = Interlocked.Increment(ref _globalInstanceCount);
        Trace.WriteLine(string.Format("TestClass ({0}) - Constructor called", _instanceId));
    }
    public void ByeBye()
    {
        Trace.WriteLine(string.Format("TestClass ({0}) - ByeBye called", _instanceId));
    }
    void IDisposable.Dispose()
    {
        Trace.WriteLine(string.Format("TestClass ({0}) - Dispose called", _instanceId));
    }
}


class Program
{
    static void Main(string[] args)
    {
        {
            Trace.WriteLine("Testing as a singleton");
            var container = new WindsorContainer()
                             .Register(Component.For<TestClass>()
                                         .LifeStyle.Singleton
                                         .OnDestroy(t => t.ByeBye())
                                       );
            TestClass tc = container.Resolve<TestClass>();
            Trace.WriteLine("Releasing the component");
            container.Release(tc);
            Trace.WriteLine("Disposing of the container");
            container.Dispose();
        }

        {
            Trace.WriteLine("Testing transient");
            var container = new WindsorContainer()
                                .Register(Component.For<TestClass>()
                                    .LifeStyle.Transient
                                    .OnDestroy(t => t.ByeBye())
                                    );
            TestClass tc = container.Resolve<TestClass>();
            Trace.WriteLine("Releasing the component");
            container.Release(tc);
            Trace.WriteLine("Disposing of the container");
            container.Dispose();
        }

    }
}

这会产生以下输出。如您所见,ByeByeDispose 之后调用。

作为单例进行测试

TestClass (1) - 构造函数调用

释放组件

容器的处置

TestClass (1) - 调用 Dispose

TestClass (1) - ByeBye 被调用

测试瞬态

TestClass (2) - 构造函数调用

释放组件

TestClass (2) - 调用 Dispose

TestClass (2) - ByeBye 被调用

容器的处置

我尝试使用拦截器解决此问题,但事实证明,Windsor 框架调用 Dispose在原始组件上绕过任何拦截器

            Trace.WriteLine("Testing transient with interceptor");
            var container = new WindsorContainer()
                                .Register(Component.For<TestClassInterceptor>().LifeStyle.Transient,
                                          Component.For<TestClass>()
                                                    .LifeStyle.Transient
                                                    .OnDestroy(t => t.ByeBye())
                                                    .Interceptors<TestClassInterceptor>()
                                        );
            TestClass tc = container.Resolve<TestClass>();
            tc.Hello();
            Trace.WriteLine("Releasing the component");
            container.Release(tc);
            Trace.WriteLine("Disposing of the container");
            container.Dispose();

产生以下输出。请注意,TestClass (3) - Dispose 的调用与拦截器无关。

使用拦截器测试瞬态

TestClassInterceptor (1) - 构造函数调用

TestClass (3) - 构造函数调用

TestClassInterceptor(一)-拦截方法“Hello”

TestClass (3) - 你好,叫来

释放组件

TestClass (3) - 调用 Dispose

TestClassInterceptor(一)-拦截方法“ByeBye”

TestClass (3) - 再见

TestClassInterceptor (1) - Dispose 调用

容器的处置

I am using the castle-windsor framework, and I want to invoke a piece of code just before the framework releases a specific (third-party) component.

I thought that I could do this by adding a delegate to OnDestroy, but the framework always calls Dispose first. (See example below).

What options do I have to invoke the code before Dispose is called?

public class TestClass : IDisposable
{
    static long _globalInstanceCount = 0;
    readonly long _instanceId;
    public TestClass()
    {
        _instanceId = Interlocked.Increment(ref _globalInstanceCount);
        Trace.WriteLine(string.Format("TestClass ({0}) - Constructor called", _instanceId));
    }
    public void ByeBye()
    {
        Trace.WriteLine(string.Format("TestClass ({0}) - ByeBye called", _instanceId));
    }
    void IDisposable.Dispose()
    {
        Trace.WriteLine(string.Format("TestClass ({0}) - Dispose called", _instanceId));
    }
}


class Program
{
    static void Main(string[] args)
    {
        {
            Trace.WriteLine("Testing as a singleton");
            var container = new WindsorContainer()
                             .Register(Component.For<TestClass>()
                                         .LifeStyle.Singleton
                                         .OnDestroy(t => t.ByeBye())
                                       );
            TestClass tc = container.Resolve<TestClass>();
            Trace.WriteLine("Releasing the component");
            container.Release(tc);
            Trace.WriteLine("Disposing of the container");
            container.Dispose();
        }

        {
            Trace.WriteLine("Testing transient");
            var container = new WindsorContainer()
                                .Register(Component.For<TestClass>()
                                    .LifeStyle.Transient
                                    .OnDestroy(t => t.ByeBye())
                                    );
            TestClass tc = container.Resolve<TestClass>();
            Trace.WriteLine("Releasing the component");
            container.Release(tc);
            Trace.WriteLine("Disposing of the container");
            container.Dispose();
        }

    }
}

This produces the following output. As you can see, ByeBye is called after Dispose.

Testing as a singleton

TestClass (1) - Constructor called

Releasing the component

Disposing of the container

TestClass (1) - Dispose called

TestClass (1) - ByeBye called

Testing transient

TestClass (2) - Constructor called

Releasing the component

TestClass (2) - Dispose called

TestClass (2) - ByeBye called

Disposing of the container

I have attempted to solve this using an interceptor, but it turns out that the Windsor framework calls Dispose on the original component bypassing any interceptors.

            Trace.WriteLine("Testing transient with interceptor");
            var container = new WindsorContainer()
                                .Register(Component.For<TestClassInterceptor>().LifeStyle.Transient,
                                          Component.For<TestClass>()
                                                    .LifeStyle.Transient
                                                    .OnDestroy(t => t.ByeBye())
                                                    .Interceptors<TestClassInterceptor>()
                                        );
            TestClass tc = container.Resolve<TestClass>();
            tc.Hello();
            Trace.WriteLine("Releasing the component");
            container.Release(tc);
            Trace.WriteLine("Disposing of the container");
            container.Dispose();

Results in the following output. See that TestClass (3) - Dispose is called independently of the interceptor.

Testing transient with interceptor

TestClassInterceptor (1) - Constructor called

TestClass (3) - Constructor called

TestClassInterceptor (1) - Intecepting Method "Hello"

TestClass (3) - Hello called

Releasing the component

TestClass (3) - Dispose called

TestClassInterceptor (1) - Intecepting Method "ByeBye"

TestClass (3) - ByeBye called

TestClassInterceptor (1) - Dispose called

Disposing of the container

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文