简体   繁体   中英

StructureMap and factory classes

I have som factory classes in my code and do not like the call to Structermap. How should i do this the right way?

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);
    }
}

I don't see the problem in using structure map this way. What do you not like about the current solution?

You could use named instances that you will not even need the factory anymore. structuremap link

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

You can than retrieve the correct one by just calling

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

If you absolutely do not want your ManagerBaseFactory to use the container, you could give it access to all of the ManagerBase implementations from the container, and have it return the correct one. When StructureMap sees an IEnumerable of a type in a constructor, it will inject all instances of that type that it knows about.

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));
    }
}

And of course you need to make sure all of your ManagerBase implementations are loaded in the container:

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

It isn't clear what part you object to. One improvement you could make is to have ManagerBaseFactory take in an IContainer in its constructor, which you can use in place of the ObjectFactory static gateway. Then you can pull ManagerBaseFactory out of the container, and the container will inject itself into the factory. The factory will be easier to unit test without the static dependency.

You could also put the return statements directly in the switch so you can take advantage of generics:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM