简体   繁体   English

依赖注入和接口的许多实现

[英]Dependency injection and many implementations of interface

I have a small problem with using dependency injection in my project.在我的项目中使用依赖注入有一个小问题。 To describe problem I will use simple example.为了描述问题,我将使用简单的示例。 Let's assume that I'm writing logger aplication and my end user is able to choose if log should be saved to file or written to the console.假设我正在编写记录器应用程序,并且我的最终用户能够选择是否应将日志保存到文件或写入控制台。 User control it by choosing checkboxes in running app.用户通过在运行的应用程序中选择复选框来控制它。 He can select both or only one.他可以 select 两者或仅一个。 After selecting he clicks button "LOG" to perform action.选择后,他单击“LOG”按钮执行操作。 Now what I understand from my knowledge of DI I should create interfaces:现在,根据我对 DI 的了解,我应该创建接口:

public interface ILogger
{ 
   void log();
}

And two implementations和两个实现

public class ConsoleLogger : ILogger
{
    public void log()
    {
      ...
    }
}

public class FileLogger : ILogger
{
    public void log()
    {
      ...
    }
}

I know that I can register both implementations in for example unity container and get them in constructor by using table but then I can't identify which implementations is FileLogger and which is ConsoleLogger (In case when user select only one checkbox)我知道我可以在例如统一容器中注册这两个实现,并通过使用表在构造函数中获取它们,但是我无法确定哪些实现是 FileLogger,哪些是 ConsoleLogger(如果用户 select 只有一个复选框)

Second options is use service locator pattern to resolve implementations from ioc by name.第二种选择是使用服务定位器模式通过名称解析来自 ioc 的实现。 I dont know if it is a good approach我不知道这是否是一个好方法

In my real application I will have more options than two and there will be a lot of shared interfaces by each option.在我的实际应用程序中,我将有两个以上的选项,并且每个选项都会有很多共享接口。

Maybe better is use MEF?也许更好的是使用MEF?

Application will be written in WPF + PRISM.应用程序将写入 WPF + PRISM。

The way I usually do this is to make your class depend on an ILoggerFactory , which can create ILogger instances given a name.我通常这样做的方式是让您的 class 依赖于ILoggerFactory ,它可以创建ILogger实例给定名称。

The factory implementation, LoggerFactory , would hold the container's kernel and be able to resolve the component by name.工厂实现LoggerFactory将保存容器的 kernel 并能够按名称解析组件。

Notice how the factory interface only tells you that it can create objects - it doesn't give you any hint about any underlying kernel, or DI framework - the factory implementation is the one that knows about those details.请注意,工厂接口如何只告诉您它可以创建对象 - 它没有给您任何有关任何底层 kernel 或 DI 框架的提示 - 工厂实现是了解这些细节的那个。

Something like this:像这样的东西:

public class MyLoggingClass
{
    private readonly ILoggerFactory _loggerFactorty;

    public MyLoggingClass(ILoggerFactory factory)
    {
        _loggerFactorty = factory;

        var fileLogger = _loggerFactorty.Create("fileLogger");
        var consoleLogger = _loggerFactorty.Create("consoleLogger");
    }
}


public class LoggerFactory : ILoggerFactory
{
    public ILogger Create(string key)
    {
        return kernel.Resolve<ILogger>(key);
    }
}

Frameworks like Castle Windsor even give you these factories for free: you don't even have to write its implementation.像 Castle Windsor 这样的框架甚至免费为您提供这些工厂:您甚至不必编写它的实现。

Service locator pattern is an anti-pattern now and should not be used.服务定位器模式现在是一种反模式,不应使用。

In your case, it's better to use Strategy design pattern because you're creating objects dynamically at runtime.在您的情况下,最好使用策略设计模式,因为您在运行时动态创建对象。

The differences between dependency injection and strategy pattern are subtle but there are.依赖注入和策略模式之间的差异是微妙的,但确实存在。 For more information:了解更多信息:

Strategy Pattern vs Dependency Injection 策略模式与依赖注入

What is the difference between Strategy pattern and Dependency Injection? 策略模式和依赖注入有什么区别?

To create objects dynamically, you could use factory method design pattern or abstract factory .要动态创建对象,您可以使用工厂方法设计模式或抽象工厂

I don't see the point of creating a custom factory if all you want is basic IOC functionality.如果您想要的只是基本的 IOC 功能,我看不出创建自定义工厂的意义。 If you're going to develop the application using WPF and Prism, a good approach is to use one of the supported IOC containers.如果您要使用 WPF 和 Prism 开发应用程序,一个好的方法是使用受支持的 IOC 容器之一。 I have used Unity a lot and really like it.我经常使用 Unity,并且非常喜欢它。 Another supported version is the MEF (as you suggested).另一个受支持的版本是 MEF(如您所建议的)。

Both of them allow you to resolve interfaces using names.它们都允许您使用名称解析接口。 It is not bad practice and gives a structured way of resolving the correct interface.这是不错的做法,并提供了解决正确界面的结构化方法。

For using Prism with Unity or Mef, see here:要在 Unity 或 Mef 中使用 Prism,请参见此处:

https://docs.microsoft.com/en-us/previous-versions/msp-np/gg430868(v=pandp.40) https://docs.microsoft.com/en-us/previous-versions/msp-np/gg430868(v=pandp.40)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Provider 实现接口时的依赖注入循环依赖 - Dependency Injection circular dependency when using a Provider for interface implementations .NET Core 依赖注入 - 解析接口的实现和 IEnumerable - .NET Core Dependency Injection - Resolve implementations and IEnumerable of interface 在运行时检索接口的实现时,使用依赖注入有什么好处? - What are the benefits of using Dependency Injection when retrieving implementations of an interface at runtime? 使用依赖注入注入多个实现 - Injecting multiple implementations with Dependency injection 如何使用采用同一接口的两个实现的类构造函数解决依赖注入 - How to resolve dependency injection with class constructor that takes two implementations of the same interface .NET 单元测试中的核心依赖注入 - 具有多个具体实现的接口 - Func<string, iinterface></string,> - .NET Core Dependency Injection in a Unit Test - An Interface With Multiple Concrete Implementations - Func<string, IInterface> 接口未通过依赖注入实现 - Interface not implemented with dependency injection 许多接口实现的 Autofac 注册 - Autofac registration for many interface implementations 测试接口的许多实现(TDD) - Testing many implementations of an interface (TDD) 城堡温莎依赖注入与多种具体实现 - Castle Windsor Dependency Injection with Multiple Concrete Implementations
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM