StructureMap和工厂类

本文关键字:工厂 StructureMap | 更新日期: 2023-09-27 17:58:49

我的代码中有一些工厂类,不喜欢对Structermap的调用。我该怎么做才是正确的?

class ManagerBaseFactory
{
    public ManagerBase GetInstance(SomeEnum e)
    {
        Type t;
        switch (e)
        {
            case SomeEnum.A:
                t = typeof(Manager1);
            case SomeEnum.B:
                t = typeof(Manager2);
            case SomeEnum.C:
                t = typeof(Manager3);
        }
        return (ManagerBase)StructureMap.ObjectFactory.GetInstance(t);
    }
}

StructureMap和工厂类

我认为以这种方式使用结构映射没有问题。您不喜欢当前解决方案的哪些方面?

您可以使用命名实例,甚至不再需要工厂。结构图链接

public class ServicesRegistry : Registry
{
    public ServicesRegistry()
    {
        For< ManagerBase >().Use< Manager1 >().Named("A");
        For< ManagerBase >().Use< Manager2 >().Named("B");
        For< ManagerBase >().Use< Manager3 >().Named("C");
    }
}

你可以通过调用来检索正确的

SomeEnum e = SomeEnum.A;
ObjectFactory.GetNamedInstance<ManagerBase>(e.ToString());

如果您绝对不希望您的ManagerBaseFactory使用容器,您可以让它访问容器中的所有ManagerBase实现,并让它返回正确的实现。当StructureMap在构造函数中看到某个类型的IEnumerable时,它将注入它所知道的该类型的所有实例。

class ManagerBaseFactory
{
    private readonly IEnumerable<ManagerBase> _managers;
    public ManagerBaseFactory(IEnumerable<ManagerBase> managers)
    {
        _managers = managers;
    }
    public ManagerBase GetInstance(SomeEnum e)
    {
        Type t;
        switch (e)
        {
            case SomeEnum.A:
                t = typeof(Manager1);
                break;
            case SomeEnum.B:
                t = typeof(Manager2);
                break;
            case SomeEnum.C:
                t = typeof(Manager3);
                break;
            default:
                return null;
        }
        return _managers.FirstOrDefault(m => m.GetType().Equals(t));
    }
}

当然,您需要确保所有的ManagerBase实现都加载在容器中:

var container = new Container(x =>
{
    x.Scan(scan =>
    {
        scan.TheCallingAssembly();
        scan.AddAllTypesOf<ManagerBase>();
    });
});

不清楚您反对哪个部分。您可以做的一个改进是让ManagerBaseFactory在其构造函数中接受IContainer,您可以使用它来代替ObjectFactory静态网关。然后,您可以将ManagerBaseFactory从容器中拉出,容器将自己注入到工厂中。在没有静态依赖的情况下,工厂将更容易进行单元测试。

您也可以将return语句直接放在switch中,这样您就可以利用泛型:

case SomeEnum.A:
  return _container.GetInstance<Manager1>();