初始化接口的正确方法是什么?

时间:2019-04-16 02:34:57

标签: c#

我的不是Web应用程序。这完全是C#库。我的界面非常简单,位于一个单独的C#库中:

public interface IDataRepository
{
    Task<string> GetAppSettingAsync(string name);
}

我正在另一个C#库中访问此DLL。

public class BaseConsumer
{
    public IDataRepository DataRepository => new DataRepository();

    public async Task<string> AppSetting()
    {
       return await DataRepository.GetAppSettingAsync("name");
    }
}

在Web / Windows应用程序中,我们进行依赖项注入并通过构造函数注入存储库/服务。这里没有选择,因为我的库具有无参数构造函数。

如何获取IDataRepository而不是使用新的DataRepository进行初始化?

2 个答案:

答案 0 :(得分:0)

这不遵循正常的DI模式。但是,如果其他解决方案失败,则可能会有所帮助。您可以使用DI进行绑定:

MyDIFramework.Bind<IDataRepository>().To<DataRepository>();

如果您使用的是Autofac,它将如下所示:

builder.RegisterType<DataRepository>().As<IDataRepository>();

然后您可以在需要时解决它:

var dataRepository = DependencyResolver.Current.GetService<IDataRepository>();

这样,您可以保持无参数状态。

答案 1 :(得分:0)

在处理不符合依赖项注入的遗留代码时,可以考虑的选择是上面的服务定位器模式。我采用的变体称为惰性属性注入:

使用Autofac,我将容器包装在Singleton中以便于访问。

然后在需要依赖项的服务类中:

private IDataRepository _dataRepository = null;    
public IDataRepository DataRepository 
{
    get { return _dataRepository ?? (_dataRepository = ContainerRegistry.Instance.Resolve<IDataRepository>());}
    set { _dataRepository = value; }
}

此方法的好处是,仅在需要依赖项时才解决依赖关系,并且仅在第一次需要依赖项时才解决。这也是一个非常简单的验证检查,以确保在不应使用的地方都不会使用服务定位器。 ContainerRegistry.Resolve应该永远只能在这些Getter中找到,因此,如果您发现它在其他任何地方都可以使用,请与该开发人员联系,以避免在难以测试的地方推广它的使用。通过实例化您的被测类并通过公共设置器提供模拟,该模式对于单元测试是完全可测试的。 (同样,您只需要提供预期测试会触发的依赖项的模拟即可。)对于测试代码,您可以将容器注册表设置为通过将拦截器注册为夹具设置的一部分来引发Resolve调用。