结构图-相同接口的两个实现 [英] structuremap - two implementations of same interface

查看:60
本文介绍了结构图-相同接口的两个实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有以下ctor的服务类:

I have a service class with the following ctor:

public class (IMessageService emailService, IMessageService smsService)
{ ... }

IMessageService (电子邮件和短信)。如何配置容器以正确解析此构造函数?

and two implementations of IMessageService (email and sms). How do I configure the container to resolve this constructor correctly? Is this where named instances come in, or is that for another scenario?

推荐答案

可以使用命名实例或智能实例来解决此问题...

You could use named instances or smart instances to solve this...

// Named instances
this.For<IMessageService>().Use<EmailService>().Named("emailService");
this.For<IMessageService>().Use<SmsService>().Named("smsService");



// Smart instances
var emailService = this.For<IMessageService>().Use<EmailService>();
var smsService = For<IMessageService>().Use<SmsService>();

this.For<ISomeService>().Use<SomeService>()
    .Ctor<IMessageService>("emailService").Is(emailService)
    .Ctor<IMessageService>("smsService").Is(smsService);

但是我认为您的设计需要一些工作。您的服务知道emailService和SMS服务之间的区别,这违反了Liskov替代原则。比注入2个相同类型的参数更好的方法是使用复合模式

But I would argue that your design needs some work. The fact that your service knows the difference between an emailService an an SMS service is a violation of the Liskov Substitution Principle. A better approach than injecting 2 parameters of the same type is to use a composite pattern.

public class CompositeMessageService : IMessageService
{
    private readonly IMessageService messageServices;

    public CompositeMessageService(IMessageService[] messageServices)
    {
        if (messageServices == null)
            throw new ArgumentNullException("messageServices");
        this.messageServices = messageServices;
    }

    public void Send(IMessage message)
    {
        foreach (var messageService in this.messageServices)
        {
            messageService.Send(message);
        }
    }
}

您的原始服务需要仅接受 IMessageService 的单个实例。它不需要知道要处理的 IMessageService 类型的详细信息。

Your original service then needs to only accept a single instance of IMessageService. It does not need to know the details of what type of IMessageService it is dealing with.

public SomeService(IMessageService messageService)

在StructureMap中,您可以轻松注册的所有实例IMessageService,它将自动将它们注入IMessageService的构造函数参数数组中。

In StructureMap, you can easily register all instances of IMessageService and it will automatically inject them into a constructor argument array of IMessageService.

this.Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.AssemblyContainingType<IMessageService>();
            scan.AddAllTypesOf<IMessageService>();
        });

或者您可以显式注入实例。

Or you can inject instances explicitly.

        this.For<IMessageService>().Use<CompositeMessageService>()
            .EnumerableOf<IMessageService>().Contains(x =>
            {
                x.Type<EmailService>();
                x.Type<SmsService>();
            });

这意味着可以更改您的配置以更改首先调用服务的顺序。在当前的设计中,这些详细信息被硬编码到接受2个参数的服务中。

This means your configuration can be changed to change the order of which service is called first. With your current design, those details are hard coded into the service that accepts the 2 parameters.

此外,您还可以添加其他消息服务或删除现有消息服务。无需更改设计。

Additionally, you gain the ability to add additional message services or remove existing message services without changing your design.

这篇关于结构图-相同接口的两个实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆