重新创建对象和 DI

Posted

技术标签:

【中文标题】重新创建对象和 DI【英文标题】:Recreating an object and DI 【发布时间】:2021-08-29 22:39:49 【问题描述】:

我正在编写一个与 API 客户端对象一起使用的类,该对象有时会损坏并且必须从使用它的对象内部重新创建。使用依赖注入的最佳方法是什么?我对从类内部调用 DI 框架犹豫不决,因为它使我的代码依赖于它。

public class MyObject

    protected IMyAPIClient Client  get; set; 

    public MyObject(IMyAPIClient client)
    
        Client = client;
    

    protected async Task<ReturnType> Run<ReturnType>(Func<Task<ReturnType>> action, int attempt = 1)
    
        try
        
            return await action();
        
        catch(Exception exception)
        
            Client = await GetNewClient();
            if(attempt > MAX_ATTEMPTS)
            
                throw new Exception($"Failed attempt times", exception);
            
            
            return await Run(action, attempt++);
        
    

    protected async Task<IMyAPIClient> GetNewClient()
    
        // what to do here?
    

我想出的一个解决方案是在一个知道 IMyAPIClient 类型的类中实现 IMyAPIClient 并重新创建它,从而绕过 DI 框架。我想知道这是否明智,或者是否有更好的方法?

【问题讨论】:

如果您的 IMyAPIClient 实例不稳定,我会尝试修复它。如果你改写你的问题并添加导致问题的代码,也许这里有人可以找到真正的问题。 BR 您使用的是什么 IoC 框架?例如,如果您使用 Autofac,这很容易 - 只需注入一个 func。 通常最好找出问题的原因而不是更换它。否则我们永远学不会 【参考方案1】:

我会首先尝试解决 ApiClient 的问题。对有缺陷的代码使用变通办法很少是一个好主意,但有时可能需要第三方代码。如果问题出在第三方代码中,也可能建议将其放在单独的进程中,否则您无法知道失败是否有一些意想不到的副作用。

要创建新对象,我建议注入某种工厂。具体如何完成将取决于 DI/IoC 框架。最简单的可能是Func&lt;IMyAPIClient&gt;,但另一种选择是显式工厂类。您可以选择工厂是应该使用 IoC 容器来构造对象,还是直接构造它。此外,一些 IoC 框架会以某种特殊的方式处理工厂,而另一些框架可能需要像其他所有东西一样注册工厂。查看您的框架的文档,了解应如何管理工厂。

如果可能,我还建议将重启逻辑移至装饰器。这样就和使用分离了,在有多个用户或者需要更新逻辑的情况下应该更加灵活。但是,注册装饰器可能有点棘手,以确保它们正常工作,但这也取决于您的 IoC 框架。

【讨论】:

【参考方案2】:

我通过创建一个创建 IMyAPIClient 的工厂类解决了这个问题。 这样我就可以在这个工厂类中处理依赖注入,而无需让其他代码依赖于 DI 框架。

public class MyObject

    protected IMyAPIClientFactory ClientFactory  get; set; 

    public MyObject(IMyAPIClientFactory clientFactory)
    
        ClientFactory = clientFactory;
        Client = clientFactory.CreateClient();
    

    protected async Task<ReturnType> Run<ReturnType>(Func<Task<ReturnType>> action, int attempt = 1)
    
        try
        
            return await action();
        
        catch(Exception exception)
        
            Client = await clientFactory.CreateClient();
            if(attempt > MAX_ATTEMPTS)
            
                throw new Exception($"Failed attempt times", exception);
            
            
            return await Run(action, attempt++);
        
    

【讨论】:

以上是关于重新创建对象和 DI的主要内容,如果未能解决你的问题,请参考以下文章

spring的控制反转(IOC)和依赖注入(DI)

IoC和DI

设计模式之注册树模式

spring 之 DI

Spring(DI,AOP) 理解

ioc(Inversion of Control)控制反转和DI