在Simple Injector中使用运行时数据获取实例

时间:2015-03-14 02:58:19

标签: c# architecture dependency-injection inversion-of-control simple-injector

我有一个应用程序,它根据数据库中的用户配置构建其用户界面。我创建了一个名为IAction的接口,看起来像这样;

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

像AddItemAction这样的实现看起来像这样;

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

    // Rest of implementation
}

在启动时,我遍历来自数据库的ActionConfigDto集合。它们指定了一些可配置的动作参数以及一个ActionType,我用它来匹配相应的Action。可能有多个ActionConfigDto具有相同的ActionType,因此应为每个配置创建相应Action的多个实例。一旦创建了IAction实例,就应该将配置传递给动作配置方法。

我使用Simple Injector作为我的DI容器,但我没有找到一个示例,说明如何使用我在运行时才知道的数据来实例化Action的实例。

我知道Simple Injector的编写方式是为了阻止糟糕的做法,所以我的方法是错的,你会如何实现这个要求,或者有没有办法用Simple Injector实现这种配置?

1 个答案:

答案 0 :(得分:4)

在做了一些搜索之后,我在resolving instances by key找到了一些文档并实现了一个ActionFactory,它手动注册每种类型。

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

我按如下方式配置工厂;

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有很好的文档,我没有想过使用密钥来注册动作,直到找到链接。