类库中的依赖注入

时间:2016-12-02 13:49:51

标签: .net reflection dependency-injection architecture autofac

有两个项目的解决方案我遇到了DI问题。 该解决方案由一个类库和一个WebApi2应用程序组成(它使用了类库并公开了一个api)。

我在类库中定义了一个Autofac.module,用于设置项目中的所有DI。

在WebApi2项目中,我创建了DI容器(使用Autofac.WebApi2)并从类库中加载模块。现在,当WepApi2项目中的api控制器请求类库中的服务时,它们会创建所有依赖项,这一切都很有效!

问题是我现在在类库中需要从字符串中实例化一些类(最终来自数据库),据我所知,通过使用反射来实现这一点的唯一方法,所以我喜欢这样:

var ruleType = Type.GetType(rule.RuleImplementation.Implementation);
var rule = (IRule)Activator.CreateInstance(ruleType,param1,param2);

问题是实现IRule接口的类还有需要解决的依赖项,这就是让我在键盘上敲打一段时间的原因。

是否有可能以某种方式使用反射和autoFac一起实例化对象?我仍然需要能够将我的参数传递给对象。

...或者有没有办法以某种方式访问​​容器(在webApi2程序集中创建)并使用它来解决它?我想这将是某种服务模式,我认为这种模式被认为是一种反模式。

我该怎么办?所有输入都非常感激。

2 个答案:

答案 0 :(得分:2)

使用Activator.CreateInstance创建组件是一个坏主意,因为它基本上意味着您重新实现了容器为您做的逻辑,但没有DI库为您提供的功能和安全保护。

  

我在类库中定义了一个Autofac.module,用于设置项目中的所有DI。

这是你麻烦的根源所在。应用程序中应该只有一个位置组成(并注册)对象图,这就是应用程序Composition Root。可以将此组合根视为位于表示层(Web API)之上的单独层,即使组合根(层)和表示层都位于同一项目中也很常见。 p>

执行此操作可以解决问题,因为在合成根目录中您已经可以访问容器。

允许使用来自数据库的某些定义创建规则的好方法是定义IRuleActivator抽象。这个抽象可以在您的库中定义,并在组合根目录中实现。这允许实现包装容器,而库不知道容器的存在:

// Defined in the library
public interface IRuleActivator
{
    IRule GetRule(RuleData rule);
}

// Defined in the Compostion Root
public sealed class AutofacRuleActivator : IRuleActivator
{
    private readonly IComponentContext context;
    public AutofacRuleActivator(IComponentContext context) {
        this.context = context;
    }

    public IRule GetRule(RuleData rule) {
        Type ruleType = Type.GetType(rule.RuleImplementation.Implementation);
        return (IRule)this.context.Resolve(ruleType);
    }
}

答案 1 :(得分:1)

您可以为IRule创建工厂:

public IRuleFactory
{
   IRule CreateRule(params);
}

对于参数,我会选择某种IParamsProviders,然后将其注入到IRuleFactory的实现中,RuleImpl只是你对象构造的实现,也可以反射:

public class RuleFactory : IRuleFactory
{
    public RuleFactory(IParamsProvider provider)
    {
        ...
    }

    public IRule CreateRule()
    {
        return new RuleImpl(provider.Param1, provider.Param2);
    }
}

将这些接口注册到Ioc中并将它们注入服务处理程序。