Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# NuGet包库中的依赖注入_C#_Dependency Injection_Inversion Of Control_Castle Windsor - Fatal编程技术网

C# NuGet包库中的依赖注入

C# NuGet包库中的依赖注入,c#,dependency-injection,inversion-of-control,castle-windsor,C#,Dependency Injection,Inversion Of Control,Castle Windsor,这是基于本问题中讨论的概念 我正在从事一个使用Castle.Windsor进行DI的项目,并引用了几个定制的NuGet包。我已经在通过NuGet引用的一个类库(我们称之为MyNugetLib)中安装了Castle.Windsor,并且在该库中的IWindsorContainer上定义了一个扩展方法,该方法注册本地服务 public static class WindsorContainerExtensions { public static void RegisterMyNugetLi

这是基于本问题中讨论的概念

我正在从事一个使用Castle.Windsor进行DI的项目,并引用了几个定制的NuGet包。我已经在通过NuGet引用的一个类库(我们称之为MyNugetLib)中安装了Castle.Windsor,并且在该库中的IWindsorContainer上定义了一个扩展方法,该方法注册本地服务

public static class WindsorContainerExtensions
{
    public static void RegisterMyNugetLibServices(this IWindsorContainer container)
    {
        container.RegisterLocalServices();
    }
    
    private static void RegisterLocalServices(this IWindsorContainer container)
    {
        container.Register(...)
    }
}
引用此NuGet包(我们称之为MyProj)的项目也使用Windsor,并在安装程序中调用NuGet包中定义的扩展方法。这一切都有效。 我的问题是如何将Windsor容器引用从MyProj传递到MyNugetLib?我曾尝试将IWindsorContainer注入到我需要的类的构造函数中,但该类使用如下惰性实例化:

private static readonly Lazy<MyClass> LazyInstance = new Lazy<MyClass>(() => new MyClass());
    
private MyClass() {}

public static MyClass Instance => LazyInstance.Value;
Lib.MyClass.Instance
我成功完成这项工作的唯一方法是在MyClass中公开一个公共属性,该属性在MyProj中用于设置WindsorContainer

public IWindsorContainer DIContainer { get; set; }
在MyProj中

Lib.MyClass.DIContainer = MyProj.WindsorContainer
namespace MyProj
{
    public class WindsorInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            // enable registration of lazy services
            container.Register(Component.For<ILazyComponentLoader>().ImplementedBy<LazyOfTComponentLoader>());
            
            container.Register(Classes.FromAssemblyContaining(typeof(MyNugetLib.DI.IMyNugetLibSingleton)).BasedOn<MyNugetLib.DI.IMyNugetLibSingleton>().WithService.FromInterface().LifestyleSingleton());
            
            container.Register(Classes.FromAssemblyContaining(typeof(MyNugetLib.DI.IMyNugetLibTransient)).BasedOn<MyNugetLib.DI.IMyNugetLibTransient>().WithService.FromInterface().LifestyleTransient());
            
            // register local services
        }
    }
    
    public class MyLocalClass : IMyLocalClass
    {
        private Lazy<MyNugetLib.IMyClass> myNugetLibLazyService
        
        public MyLocalClass(Lazy<MyNugetLib.IMyClass> lazyService)
        {
            this.myNugetLibService = lazyService;
        }
        
        internal MyLocalType DoSomethingHere() 
        {
            this.myNugetLibService.Value.DoSomething();
            // etc
        }
    }
}
我不是特别喜欢这个。有更好的方法吗


更新:(感谢insane_开发者的建议)

问题是:如何在惰性构造函数中注入依赖项?如果我能做到这一点,那么我就可以从MyNugetLib中删除对Windsor的依赖

所以我会

private IService1 service1;
private IService2 service2;

private MyClass(IService1 myService1, IService2 myService2) 
{
    this.service1 = myService1;
    this.service2 = myService2
}

public static MyClass Instance => LazyInstance.Value;

private static readonly Lazy<MyClass> LazyInstance = new Lazy<MyClass>(() => new MyClass(???));
专用iSeries服务1;
私人IService2服务2;
私有MyClass(IService1 myService1、IService2 myService2)
{
this.service1=myService1;
this.service2=myService2
}
公共静态MyClass实例=>LazyInstance.Value;
private static readonly Lazy Lazy实例=new Lazy(()=>new MyClass(???));

如何编写上面的func,使其在构造函数中注入依赖项?

我从未使用Castle.Windsor,但我认为它与其他容器类似。您实际上不需要将对容器的引用传递到库中。您应该能够在主应用程序中配置所有映射,该应用程序具有对库的引用。如果你按照你的建议去做,你将对Castle.Windsor有一个具体的依赖,这不是一个好主意。

多亏了@Inasane\u developer的建议,我能够以一种更干净的方式来做这件事。 问题是MyNugetLib使用的是使用
Lazy
创建的静态单例。依赖项不能注入到那些构造函数中,因此我试图找到一种好方法来传递对DI容器的引用。不管如何,它在MyNugetLib中引入了对DI包的直接依赖,这并不好。更好的解决方案是在MyNugetLib中一致地使用依赖项注入,使用静态单例重构类,使普通构造函数具有注入的依赖项,并从主应用程序(MyProj)注册这些依赖项。为了做到这一点,我必须重构MyProj使用一些MyNugetLib类的方式,这样它就不再通过静态属性引用单例,而是通过注入依赖项引用单例,注入依赖项在主DI容器中注册为单例,注入为惰性依赖项。 这就是我(概念上)所做的

然后,在MyProj中

namespace MyProj
{
    public class WindsorInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            // enable registration of lazy services
            container.Register(Component.For<ILazyComponentLoader>().ImplementedBy<LazyOfTComponentLoader>());
            
            container.Register(Classes.FromAssemblyContaining(typeof(MyNugetLib.DI.IMyNugetLibSingleton)).BasedOn<MyNugetLib.DI.IMyNugetLibSingleton>().WithService.FromInterface().LifestyleSingleton());
            
            container.Register(Classes.FromAssemblyContaining(typeof(MyNugetLib.DI.IMyNugetLibTransient)).BasedOn<MyNugetLib.DI.IMyNugetLibTransient>().WithService.FromInterface().LifestyleTransient());
            
            // register local services
        }
    }
    
    public class MyLocalClass : IMyLocalClass
    {
        private Lazy<MyNugetLib.IMyClass> myNugetLibLazyService
        
        public MyLocalClass(Lazy<MyNugetLib.IMyClass> lazyService)
        {
            this.myNugetLibService = lazyService;
        }
        
        internal MyLocalType DoSomethingHere() 
        {
            this.myNugetLibService.Value.DoSomething();
            // etc
        }
    }
}
名称空间MyProj
{
公共类WindsorInstaller:IWindsorInstaller
{
public void安装(IWindsorContainer、IConfigurationStore)
{
//启用惰性服务的注册
container.Register(Component.For().ImplementedBy());
container.Register(Classes.FromAssemblyContaining(typeof(MyNugetLib.DI.IMyNugetLibSingleton)).BasedOn().WithService.FromInterface().LifestyleSingleton());
container.Register(Classes.FromAssemblyContaining(typeof(MyNugetLib.DI.IMyNugetLibTransient)).BasedOn().WithService.FromInterface().LifestyleTransient());
//注册本地服务
}
}
公共类MyLocalClass:IMyLocalClass
{
私有惰性myNugetLibLazyService
公共MyLocalClass(懒惰懒散服务)
{
this.myNugetLibService=lazyService;
}
内部MyLocalType DoSomethingHere()
{
this.myNugetLibService.Value.DoSomething();
//等
}
}
}
使用
IMyNugetLibSingleton
IMyNugetLibTransient
我能够用一个
register
语句注册实现这些的所有类。 我现在已经将“懒散”从MyNugetLib移到了MyProj。注入的依赖项myNugetLibLazyService仅在需要时解析。MyNugetLib的依赖项现在可以由使用者选择使用任何DI contanier来解析


我对这个解决方案很满意,但如果有人有更好的想法,我仍然愿意接受建议。

我要指出的是,在singleton类中使用公共构造函数完全违背了它作为singleton的目的。你是对的。我会改变的。谢谢我不明白Lib.MyClass.DIContainer的目的是什么,你能再解释一遍吗?它在Lib.MyClass中用于解析本地服务。例如,[code]内部IMyLibService服务{get{if(this.myLibService==null){this.myLibService=this.DIContainer.Resolve();}返回this.myLibService;}}}[/code]@erionpc不使用静态字段,相反,创建一个类似MyClassProvider的类,将Instance和LazyInstance作为实例字段(所以不是静态的)。然后将这个类注册为singleton并将容器传递给这个Classic。我希望MyNugetLib独立于MyProj,注册自己的服务,并且不依赖于MyProj中定义的DI容器,但我不确定这是否可行。Thanks@erionpc我真的不知道这是个多好的主意,但我想这是可能的。大概