通过枚举值创建实例 + 依赖注入

4

我在应用程序中有一些处理程序类,根据传递的枚举值在运行时创建。它看起来像这样:

public interface IMyHandler
{
    void Handle();
}

public class SimpleHandler : IMyHandler
{
    public void Handle()
    {
        //logic here...
    }
}

public class ComplexHandler : IMyHandler
{
    public void Handle()
    {
        //logic here...
    }
}

public enum HandlerTypes
{
    Simple,
    Complex
}

public class Hanlderfactory
{
    public IMyHandler CreateHandler(HandlerTypes type)
    {
        switch(type)
        {
            case HandlerTypes.Simple:
                return new SimpleHandler();
            case HandlerTypes.Complex:
                return new ComplexHandler();
            default:
                throw new NotSupportedException();
        }
    }
}

对我来说没问题。但是如果我想像这样在我的处理程序中注入一些组件,就会出现一个问题:

public class SimpleHandler : IMyHandler
{
    public SimpleHandler(IComponentOne c1, IComponentTwo c2, IComponentThree c3)
    {
        //...
    }

    public void Handle()
    {
        //logic here...
    }
}

我使用Unity IoC容器,当然希望在此处使用它。但是手动调用Resolve方法看起来很丑陋。我走错路了吗?如何优雅地将这两种模式结合起来使用?在工厂内部调用IoC容器是唯一的选择吗?

更新:我尝试使用InjectionFactory类的委托注入。它运行良好。但在这种情况下,如果我需要在两个应用程序中使用此工厂逻辑,则需要在两个应用程序的启动中注册此委托和枚举与类之间的映射。
var container = new UnityContainer();
container.RegisterType<IMyHandler, SimpleHandler>(HandlerTypes.Simple.ToString());
container.RegisterType<IMyHandler, ComplexHandler>(HandlerTypes.Complex.ToString());
container.RegisterType<Func<HandlerTypes, IMyHandler>>(new InjectionFactory(c => new Func<HandlerTypes, IMyHandler>(type => c.Resolve<IMyHandler>(type.ToString()))));

提示:public class Handler : IHandlerService<IComplexHandler> Unity可以解析类型参数。 - Aydin
你的意思是什么?我在运行时有HandlerTypes.Simple,需要创建正确类的实例。 - mtkachenko
@AydinAdn是正确的;你应该将处理程序抽象化为通用的。这将解决你的问题(以及更多)。请查看此文章 - Steven
1个回答

4

使用工厂模式和Enum一起使用是一种代码异味,这表明您需要进行更多的重构。

另一种选择是使用策略模式,例如此示例。请注意,使用Type而不是Enum确保在设计更改时只需更改一个代码片段(或者您可以使用字符串数据类型)。

另一种选择是Func注入到工厂中,以便您的DI容器可以解析实例。

将容器注入抽象工厂是创建 框架扩展点 的一种方式。只要该工厂是组合根的一部分,这就没问题了。

2
枚举值存储在数据库中,计时器应用程序从数据库检索行,并需要实例化适当的处理程序来处理此行。这是一种策略模式,但我不清楚如何定义策略类的类型?应该有一些映射关系将某些输入数据(例如来自数据库的枚举值)与策略类型联系起来。 - mtkachenko
在.NET中,所有类型都可以使用字符串表示法进行识别。您可以使用Type.GetType(string)方法将字符串转换为Type数据类型。这个字符串可以存储在数据库中,但一定不要保存版本号(如果您使用强命名,则会发生这种情况)。 - NightOwl888

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接