C#和.NET Core:向由DI创建的对象添加事件处理程序的正确方式。

huangapple go评论78阅读模式
英文:

C# and .NET Core: The proper way to add an event handler to an object created by DI

问题

我正在使用.AddTransient添加一个服务,以便在传递给任何构造函数时自动注入。当注入的对象被创建并传递给某个类的构造函数时,我需要添加一个事件处理程序。

我使用了以下代码:

builder.Services.AddTransient(factory =>
{
    var rest = factory.GetService<RestUtilityService>();
    rest.Exception += Api_Exception;
    return rest;
})

但在调试时,该代码被多次调用,导致应用程序挂起。

您能告诉我如何在对象首次创建时添加事件处理程序吗?

当然,事件应该只被订阅一次,所以它应该在首次创建时完成。

谢谢

Jaime

英文:

I am adding a service using .AddTransient to be injected automatically when it is passed to any constructor. I need to add an event handler when the injected object is created and passed to a constructor of some class.

I used this:

   builder.Services
        .AddTransient(factory =&gt;
        {
            var rest = factory.GetService&lt;RestUtilityService&gt;();
            rest.Exception += Api_Exception;
            return rest;
        })

But when debugging, that code is called several times and the application hangs.

Can you tell me how to add that event handler when the object is first created?

Of course, the event should be subscribed only once, so it should be done at first, and only, creation.

Thanks

Jaime

答案1

得分: 3

你的示例可能是无意中递归的,你应该明确地创建你的对象:

builder.Services
        .AddTransient(factory =>
        {
            var rest = new RestUtilityService(factory.GetService<SomeDependency>());
            rest.Exception += Api_Exception;
            return rest;
        })

这并不一定意味着这是解决问题的最佳方法。如果你想要集中处理异常,可能更好的方法是创建一个 IExceptionHandler,将其声明为单例,并将其作为你的 RestUtilityService 的依赖项。

英文:

Your example is probably unintentionally recursive, you should probably create your object explicitly:

builder.Services
        .AddTransient(factory =&gt;
        {
            var rest = new RestUtilityService(factory.GetService&lt;SomeDependency&gt;());
            rest.Exception += Api_Exception;
            return rest;
        })

That does not necessarily mean that this is the best approach to solve the problem. If you want some central handling of exceptions it might be better to create a IExceptionHandler, declare an implementation of this as a singleton, and make this a dependency of your RestUtilityService.

答案2

得分: 1

这段代码会导致堆栈溢出异常,因为注册部分在递归调用自身。

相反,您可以尝试以下方式之一:

builder.Services
    .AddTransient(factory =>
    {
        var rest = new RestUtilityService();
        rest.Exception += Api_Exception;
        return rest;
    })

或者:

builder.Services
    .AddTransient(factory =>
    {
        var rest = ActivatorUtilities.Create<RestUtilityService>(factory);
        rest.Exception += Api_Exception;
        return rest;
    })
英文:

This code will result in a stack overflow exception because the registration is recursively calling itself.

Instead, you might try something as follows:

   builder.Services
        .AddTransient(factory =&gt;
        {
            var rest = new RestUtilityService();
            rest.Exception += Api_Exception;
            return rest;
        })

or:

   builder.Services
        .AddTransient(factory =&gt;
        {
            var rest = ActivatorUtilities.Create&lt;RestUtilityService&gt;(factory);
            rest.Exception += Api_Exception;
            return rest;
        })

huangapple
  • 本文由 发表于 2023年6月27日 21:08:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76565214.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定