调整Unity Dependency注入以使用Lazy <t> / Func <t>

时间:2017-04-06 11:00:33

标签: c# dependency-injection unity-container

我正在开发一个使用Unity Dependancy注入的项目,但负载性能正在慢慢恶化。我正在尝试调整代码以使用Lazy<T>(或Func<T>),因此我正在尝试使用Lazy<T>(或{{1}找到使用容器注册类的方法或者有某种工厂,可以调整已注册的类型或构造函数,但我似乎无法找到可能的方法来做到这一点

目前我有很多服务类,比如

Func<T>

然后我的注册类似于

public Service1(IClassLogic<GetReq, GetRes> getClass, IClassLogic<AddReq, AddRes> addClass, IClassLogic<UpdateReq, UpdateRes> updateClass, IClassLogic<DeleteReq, DeleteRes> deleteClass....){...}

理想情况下,我不想将所有签名更改为

container.RegisterType<IClassLogic<GetReq, GetRes>, GetClass>();
container.RegisterType<IClassLogic<AddReq, AddRes>, AddClass>();
container.RegisterType<IClassLogic<UpdateReq, UpdateRes>, UpdateClass>();
container.RegisterType<IClassLogic<DeleteReq, DeleteRes>, DeleteClass>();
...

任何指针都会非常感激

2 个答案:

答案 0 :(得分:2)

防止使用Lazy<T>和{{1}}作为依赖关系来防止慢对象图初始化。这些是漏洞抽象,因为它们将实现细节泄露给消费者。这里的实现细节是这种服务的创建成本很高。

创建依赖关系花费太多时间这一事实表明您的注入构造函数做得太多,而它们应该是simple, fast and reliable

另一个明显的问题是组件中的单一责任原则违规。在构造函数中具有5个以上的依赖项是代码气味和单一责任原则违规的指示。当你需要解决非常大的对象图时,有些容器会变慢,但是当你使你的组件变小并集中注意力时,这个问题很可能就会消失,因为要构造的对象图会小得多。

答案 1 :(得分:1)

首先关于DI的一些提示:

  • 你没错,你不想改变构造函数的签名。您是IoC容器(在您的情况下为Unity)应该使您能够根据需要设计接口和使用者。否则它不是一个好的容器。
  • 当我开始使用DI(和容器)时,我会建议你自己接线。这使您可以深入了解其工作原理并提供灵活性。 Mark Seemann写了很多关于这些东西的文章。
  • 您服务的依赖关系似乎非常拥挤。你能不能通过组合一些(可能是Facade)?
  • 来重构较少的依赖关系
  • 使接口特定(非通用)使事情变得更加简单。泛型有时会造成更多弊大于利。

我编写了一个编译的快速示例(我还没有测试过)。我已经使用了一个与你的例子一致的通用接口,但是使用了一些伪实现和字符串类型作为泛型参数(未使用):

如果这是接口的实现:

public class ClassLogic : IClassLogic<string, string>
{
    public void Do()
    {
        // do stuff
    }
}

然后你可以实现一个只在需要时(通过给定的Func)创建实现的提供者,如下所示:

public class ClassLogicProvider : IClassLogic<string, string>
{
private readonly Func<IClassLogic<string, string>> innerLogicFactory;

    public ClassLogicProvider(Func<IClassLogic<string, string>> innerLogicFactory)
    {
        this.innerLogicFactory = innerLogicFactory;
    }

    public void Do()
    {
        var classLogic = this.innerLogicFactory();
        classLogic.Do();
    }
}

然后将它连接起来:

var container = new UnityContainer();
Func<IClassLogic<string, string>> classLogicFunc = () =>
        {
            // Create implementation on demand
            return new ClassLogic();
        };
container.RegisterType<IClassLogic<string, string>>(
            new InjectionFactory(c => {
                return new ClassLogicProvider(classLogicFunc);
            })
        );

这应该为您提供所需的Lazy创建时间。