7

我正在尝试将依赖注入与 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);
    }
}

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

4

1 回答 1

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

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

综合服务

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

延迟加载

有时,由于在启动期间创建过于昂贵和/或很少使用等原因,有必要推迟解决依赖项。在这些情况下,可以注入 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();

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

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 :此处提供完整示例

于 2013-01-21T16:30:15.383 回答