Dependency injection LightInjectVS(Ninject和Unity)未注册类型解析

Dependency injection LightInjectVS(Ninject和Unity)未注册类型解析,dependency-injection,ninject,unity-container,light-inject,Dependency Injection,Ninject,Unity Container,Light Inject,这对一些人来说可能是显而易见的,但是。。。有没有办法用LightInject解析未注册的类型?此外,使用DI框架自动神奇地解析对象,而无需显式注入以提高可读性,这是一种良好的做法吗 在我的示例中,我将超级全功能框架(可能是最慢的)与最轻(最快)的框架进行比较。这并不完全是个错误:D 构造函数注入(无容器) 尼尼特 private void ConfigureContainer() { Container = new StandardKernel();

这对一些人来说可能是显而易见的,但是。。。有没有办法用LightInject解析未注册的类型?此外,使用DI框架自动神奇地解析对象,而无需显式注入以提高可读性,这是一种良好的做法吗

在我的示例中,我将超级全功能框架(可能是最慢的)与最轻(最快)的框架进行比较。这并不完全是个错误:D

构造函数注入(无容器)

尼尼特

    private void ConfigureContainer()
    {
        Container = new StandardKernel();
        Container.Bind<IPersonRepository>().To<CSVRepository>()
            .InSingletonScope();
    }

    private void ComposeObjects()
    {
        Application.Current.MainWindow = Container.Get<PeopleViewerWindow>();
    }
private void ConfigureContainer()
{
容器=新的StandardKernel();
Container.Bind().To()
.InSingletonScope();
}
私有void ComposeObjects()
{
Application.Current.MainWindow=Container.Get();
}
统一

private void ConfigureContainer()
{
容器=新的UnityContainer();
Container.RegisterType(
新的ContainerControlled LifetimeManager());
}
私有void ComposeObjects()
{
Application.Current.MainWindow=Container.Resolve();
}
光注入

    private void ConfigureContainer()
    {
        Container = new ServiceContainer();
        Container.Register<IPersonRepository, CSVRepository>(
            new PerContainerLifetime());

        // Do we need to explicitly register PeopleViewerWindow with LightInject?

        Container.Register<PeopleViewerWindow>(
          factory =>
            new PeopleViewerWindow(new PeopleViewerViewModel
              (Container.GetInstance<IPersonRepository>()))
          );
    }

    private void ComposeObjects()
    {
        Application.Current.MainWindow = Container.GetInstance<PeopleViewerWindow>();
    }
private void ConfigureContainer()
{
容器=新的ServiceContainer();
集装箱。登记(
新PerContainerLifetime());
//我们是否需要使用LightInject显式注册PeopleViewerWindow?
集装箱。登记(
工厂=>
新建PeopleViewerWindow(新建PeopleViewerViewModel
(Container.GetInstance())
);
}
私有void ComposeObjects()
{
Application.Current.MainWindow=Container.GetInstance();
}

正如您对Unity和Ninject所做的那样,我看不到一种默认策略可以解决LightInject的相关依赖关系。我在LightInject方面没有经验,但至少他们没有这样的样品。可能还有其他方法可以通过扫描程序集来实现这一点,但我将按如下方式显式注入它。它将根据需要解析PeopleViewerWindow实例

        var lightContainer = new ServiceContainer();
        lightContainer.Register<IPersonRepository, CSVRepository>
        (new PerContainerLifetime());
        lightContainer.Register<PeopleViewerWindow>(
            factory =>
                new PeopleViewerWindow(new PeopleViewerViewModel
                (lightContainer.GetInstance<IPersonRepository>())));

        var instance2 = lightContainer.GetInstance<PeopleViewerWindow>();
var lightContainer=new servicecainer();
灯箱,登记
(新PerContainerLifetime());
灯箱,登记(
工厂=>
新建PeopleViewerWindow(新建PeopleViewerViewModel
(lightContainer.GetInstance());
var instance2=lightContainer.GetInstance();

我对LightInject不太熟悉,所以我不知道是否可以解析未注册的类型,但我可以回答以下问题:

使用DI自动神奇地解析对象是一种好做法吗 没有明确注入可读性的框架

我认为可以使用未注册类型解析来解析未注册类型。在某些情况下,不使用它甚至毫无意义,例如在注册开放泛型类型时。如果不这样做,您将不得不显式注册每个通用映射,这将导致您不断更改您的合成根(或者你需要做一些批注册,搜索所有可以用作泛型类型中类型参数的类型,并使用反射构建封闭的泛型版本,然后注册它们,真恶心)

然而,您应该始终尝试实现的是具有可验证的DI配置。在应用程序启动期间或使用单元测试期间,应该可以验证容器的配置。在我看来,测试这一点至关重要,因为您需要补偿通过引入依赖项注入而失去的编译时支持。Yo您可以通过迭代容器的配置并请求容器解析每个注册(某些DI库包含帮助您解决此问题的功能),或者请求容器显式解析所有根类型来测试这一点

如果选择迭代整个配置,这意味着至少所有根类型(直接从容器解析的类型,例如MVC控制器、ASP.NET页面类或WPF窗口类)需要在容器中注册。否则,容器对该类型一无所知,因此不会对其进行测试,最终导致系统在运行时仍可能失败

如果您选择迭代所有根类型,则无需显式注册它们,但您仍然需要一种通过反射查找所有根类型的方法。如果您不通过反射查找所有根类型,则意味着您必须在每次添加新根类型时更改单元测试。有时您会忘记更改测试不要使您的配置只被部分验证。这是需要防止的


因此,我倾向于显式注册根类型,这可能还有其他优点。一些DI库包含非常有用的诊断工具,可以告诉您有关对象图的各种有趣信息,并可以警告您常见的错误配置(例如)。这些工具显然只能在库知道的类型上完成其工作。库通常可以找到未明确注册的注册,只要它们是其他注册类型的依赖项,但这当然不适用于根类型。

LightInject可以解析未向conta注册的服务使用RegisterFallback方法创建一个Inner

致意


伯恩哈德·里希特(LightInject的作者)

只是比LightInject慢,可以解析未注册的类型。Simple Injector的功能与Unity一样全面,甚至有一些Unity完全缺乏的有趣功能,例如非常强大的方法。是的,我从文档中得到了同样的东西。Light Injector似乎没有未注册的类型r我希望看到这个问题的人能指出我遗漏了什么,或者告诉我什么时候、是否会发生以及为什么
    private void ConfigureContainer()
    {
        Container = new ServiceContainer();
        Container.Register<IPersonRepository, CSVRepository>(
            new PerContainerLifetime());

        // Do we need to explicitly register PeopleViewerWindow with LightInject?

        Container.Register<PeopleViewerWindow>(
          factory =>
            new PeopleViewerWindow(new PeopleViewerViewModel
              (Container.GetInstance<IPersonRepository>()))
          );
    }

    private void ComposeObjects()
    {
        Application.Current.MainWindow = Container.GetInstance<PeopleViewerWindow>();
    }
        var lightContainer = new ServiceContainer();
        lightContainer.Register<IPersonRepository, CSVRepository>
        (new PerContainerLifetime());
        lightContainer.Register<PeopleViewerWindow>(
            factory =>
                new PeopleViewerWindow(new PeopleViewerViewModel
                (lightContainer.GetInstance<IPersonRepository>())));

        var instance2 = lightContainer.GetInstance<PeopleViewerWindow>();
var container = new ServiceContainer();
container.RegisterFallback((type, s) => true, request => new Foo());
var foo = container.GetInstance<IFoo>();
public static void RegisterApiControllers(this IServiceRegistry serviceRegistry, params Assembly[] assemblies)
{
    foreach (var assembly in assemblies)
    {
        var controllerTypes = assembly.GetTypes().Where(t => !t.IsAbstract && typeof(IHttpController).IsAssignableFrom(t));
        foreach (var controllerType in controllerTypes)
        {
            serviceRegistry.Register(controllerType, new PerRequestLifeTime());
        }
    }
}