【问题标题】:Dependency Injection avoid loading everything at startup依赖注入避免在启动时加载所有内容
【发布时间】:2013-01-21 14:16:46
【问题描述】:

我正在尝试将依赖注入与 MVP 一起使用,将所需的依赖注入到构造函数中。我遇到的问题是,如果我在根 MainWindowPresenter 上使用依赖注入,它的所有子演示者及其子演示者、视图和服务都将在启动时加载。由于所有内容都是从 MainWindowPresenter 直接或间接加载的,这意味着整个应用程序将在启动时加载到内存中。

我知道在 .NET 中在启动时创建所有对象可能不会花费很多,但我不禁认为这是浪费内存,因为它们永远不会同时使用。有一些像 AboutPresenter 或 HelpPresenter 可能永远不会使用。我错过了还是依赖注入应该如何工作?有没有办法解决这个问题?

我能找到解决此问题的唯一方法是使用工厂,然后可以在需要时创建子演示者/视图/服务。例如:

class HelpFactory : AbstractHelpFactory
{
    public IHelpPresenter Create()
    {
         IHelpService helpService = new ConcreteHelpService();
         IHelpView helpView = new ConcreteHelpView();

         HelpSearchPresenter searchPresenter = HelpSearchFactory.Create();

         return HelpPresenter(helpView, helpService, searchPresenter);
    }
}

这与工厂依赖子工厂基本相同,但至少它们比演示者/视图/服务更轻,并且在需要之前不需要加载子工厂。

【问题讨论】:

    标签: .net dependency-injection mvp


    【解决方案1】:

    有几种可能的解决方案(从一般到具体):

    组合根

    确定一个作文根This is a (preferably) unique location in an application where modules are composed together这是组合所有依赖项的首选解决方案

    抽象工厂

    您可以注入 类似 依赖项的工厂,而不是注入依赖项。这将帮助您推迟创建依赖项并仅解决当前情况所需的依赖项。使用ninject.extension.factory 的示例:

    kernel.Bind<IDependencyFactory>().ToFactory();
    
    kernel
        .Bind<IDependency>()
        .To<DependencyImpl1>()
        .NamedLikeFactoryMethod((IDependencyFactory f) => f.GetJob());
    
    var abstractFactory = kernel.Get<IDependencyFactory>();
    
    var dependency = abstractFactory.GetJob(); 
    
    public abstract class IDependency { }
    public class DependencyImpl1 : IDependency { }
     
    public interface IDependencyFactory
    {
        IDependency GetJob();
        Lazy<IDependency> GetLazyJob();
    }
    

    这也有助于避免类的过度注入,例如构造函数过度注入

    聚合服务

    注入聚合处理例程的服务,而不是注入依赖项。阅读更多Refactoring to Aggregate Services

    延迟加载

    有时,由于在启动期间创建过于昂贵和/或很少使用等原因,有必要推迟解决依赖项。在这些情况下,可以注入 Lazy 而不是 IDependency。 Example using Ninject.Extension.Factory:

    kernel
        .Bind<Lazy<IDependency>>()
        .To<Lazy<IDependency>>()
        .NamedLikeFactoryMethod((IDependencyFactory f) => f.GetLazyJob());
    
    var abstractFactory = kernel.Get<IDependencyFactory>();
    
    var lazyDependencyUsingFactory = abstractFactory.GetLazyJob();
    

    使用lazy-loading w/o factory 的示例:

    kernel
        .Bind<IDependency>()
        .To<DependencyImpl1>();
        
    kernel
        .Bind(typeof (Lazy<>))
        .ToMethod(context =>
                ((ILazyLoader) Activator.CreateInstance(typeof (LazyLoader<>).MakeGenericType(context.GenericArguments),
                                                        new object[] { context.Kernel })).Loader);
    
    var lazyDependency = kernel.Get<Lazy<IDependency>>();
    
    lazyDependency.Dump();
    lazyDependency.Value.Dump();
    

    ps:提供完整示例here

    【讨论】:

    • 感谢您的帮助,我认为对我来说最好的方法是延迟加载。
    猜你喜欢
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 2018-05-05
    • 2016-12-24
    相关资源
    最近更新 更多