简体   繁体   中英

Get instances using runtime data in Simple Injector

I have an application which builds its user-interface based upon a user configuration in a database. I have created an interface called IAction which looks like this;

public interface IAction
{
    ActionType ActionType { get; }
    bool CanExecute { get; }
    void Configure(ActionConfigDto config);
    void Execute();
}

An implementation such as AddItemAction would look like this;

public class AddItemAction : IAction
{
    public ActionType ActionType 
    {
        get { return ActionType.AddItem; }
    }

    // Rest of implementation
}

On startup I iterate over a collection of ActionConfigDto's which come from the database. They specify some configurable parameters of the action along with an ActionType which I use to match up to the corresponding Action. There could be multiple ActionConfigDto's with the same ActionType so multiple instances of the corresponding Action should be created for each config. Once an instance of IAction has been created, the config should be passed to the actions Configure method.

I am using Simple Injector as my DI container but I haven't found an example of how I could instantiate instances of Action's using data I only know at runtime.

I know Simple Injector has been written in such a way as to discourage poor practices so, is my approach all wrong and how would you go about implementing this requirement or is there a way to achieve this kind of configuration with Simple Injector?

After doing some more searching I found some documentation on resolving instances by key and implemented an ActionFactory which manually registers each type.

public class ActionFactory : IActionFactory
{
    private readonly Container _container;
    private readonly Dictionary<string, InstanceProducer> _producers; 

    public ActionFactory(Container container)
    {
        _container = container;
        _producers = new Dictionary<string, InstanceProducer>(StringComparer.OrdinalIgnoreCase);
    }

    public IAction Create(ActionType type)
    {
        var action = _producers[type.ToString()].GetInstance();
        return (IAction) action;
    }

    public void Register(Type type, string name, Lifestyle lifestyle = null)
    {
        lifestyle = lifestyle ?? Lifestyle.Transient;
        var registration = lifestyle.CreateRegistration(typeof (IAction), type, _container);
        var producer = new InstanceProducer(typeof (IAction), registration);
        _producers.Add(name, producer);
    }
}

I configure the factory as follows;

var registrations =
    from type in AssemblySource.Instance.GetExportedTypes()
    where typeof (IAction).IsAssignableFrom(type)
    where !typeof (ActionDecorator).IsAssignableFrom(type)
    where !type.IsAbstract
    select new {Name = type.Name, ImplementationType = type};

var factory = new ActionFactory(container);
foreach (var reg in registrations)
{
    factory.Register(reg.ImplementationType, reg.Name);
}

container.RegisterSingle<IActionFactory>(factory);

Simple Injector has great documentation, I hadn't thought about using a key to register the Actions until I found that link.

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