gpt4 book ai didi

c# - 在运行时将接口(interface)的不同实现注入(inject)命令

转载 作者:可可西里 更新时间:2023-11-01 08:10:01 25 4
gpt4 key购买 nike

我的项目中有一个接口(interface),有 2 个类实现它:

public interface IService
{
int DoWork();
}

public class Service1:IService
{
public int DoWork()
{
return 1;
}
}

public class Service2:IService
{
public int DoWork()
{
return 2;
}
}

我有一个依赖于 IService 的命令处理程序也是:

public CommandHandler1:ICommandHandler<CommandParameter1>
{
IService _service;
public CommandHandler1(IService service)
{
_service = service
}
public void Handle()
{
//do something
_service.DoWork();
//do something else
}
}

public interface ICommandHandler<TCommandParameter>
where TCommandParameter :ICommandParameter
{
void Handle(TCommandParameter parameter);
}
public interface ICommandParameter
{
}

我要注入(inject) Service1Service2到我的CommandHandler1基于用户选择。假设我有一个 enum用户可以从中选择一个值:

public enum Services
{
Service_One,
Service_Two
}

如果用户选择 Service_One我要注入(inject) Service1到我的命令处理程序,如果他选择 Service_Two我要注入(inject) Service2到命令处理程序。

我知道我可以使用命名实例,然后调用 ObjectFactory.GetInstance<IService>().Named("Service1")例如,但是有什么办法可以通过 StructureMap 来实现吗?并防止使用 Service Locator图案?

最佳答案

防止使用运行时条件构建对象图。对象图应该是固定的。使用运行时决策来确定通过对象图的路径。

您在这里似乎缺少的是允许将请求委托(delegate)给正确的 IService 实现的抽象;我们称它为 IServiceDispatcher:

interface IServiceDispatcher
{
int DoWork(Services data);
}

sealed class ServiceDispatcher : IServiceDispatcher
{
private readonly IService service1;
private readonly IService service2;

// NOTE: Feel free to inject the container here instead, as long as
// this class is part of your composition root.
public ServiceDispatcher(IService service1, IService service2)
{
this.service1 = service1;
this.service2 = service2;
}

public int DoWork(Services data)
{
return this.GetService(data).DoWork();
}

private IService GetService(Services data)
{
switch (data)
{
case Services.Service_One: return this.service1;
case Services.Service_Two: return this.service2;
default: throw new InvalidEnumArgumentException();
}
}
}

现在您的 CommandHandler1 可以依赖于 IServiceDispatcher:

public CommandHandler1 : ICommandHandler<CommandParameter1>
{
private readonly IServiceDispatcher serviceDispatcher;
public CommandHandler1(IServiceDispatcher serviceDispatcher)
{
this.serviceDispatcher = serviceDispatcher;
}

public void Handle(CommandParameter1 commandParameter)
{
//do something
this.serviceDispatcher.DoWork(commandParameter.Service);
//do something else
}
}

请注意,IServiceDispatcher 是一个非常丑陋的名称,它在技术上描述了正在发生的事情。这是一个坏主意,因为界面应该在功能上描述你想要的东西。但是由于您没有为您的问题提供任何特定领域的上下文,所以这是我能想到的最好的名字 ;-)

关于c# - 在运行时将接口(interface)的不同实现注入(inject)命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32304836/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com