依赖注入避免在启动时加载所有内容

Use*_*ser 7 .net mvp dependency-injection

我正在尝试使用依赖注入与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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Aki*_*kim 2

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

成分根

确定组合根这是应用程序中模块组合在一起的(最好)唯一位置这是组合所有依赖项的最佳解决方案

抽象工厂

您可以注入类似依赖项的工厂,而不是注入依赖项。这将帮助您推迟依赖项创建并仅解决当前情况所需的依赖项。使用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();
}
Run Code Online (Sandbox Code Playgroud)

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

综合服务

注入聚合处理例程的服务,而不是注入依赖项。阅读更多内容重构聚合服务

延迟加载

有时,由于启动期间创建成本过高和/或很少使用等原因,有必要推迟依赖项的解析。在这些情况下,可以注入 Lazy 来代替 IDependency。使用 Ninject.Extension.Factory 的示例

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

var abstractFactory = kernel.Get<IDependencyFactory>();

var lazyDependencyUsingFactory = abstractFactory.GetLazyJob();
Run Code Online (Sandbox Code Playgroud)

使用不带工厂的延迟加载的示例:

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();
Run Code Online (Sandbox Code Playgroud)

ps:完整示例可在此处获取