如何在WPF应用中用Castle Windsor实现DI?带int参数服务注入问题
别担心,这种带基础类型参数的服务注入问题在Castle Windsor里很常见,我给你几个实用的解决办法,你可以根据自己的场景选择:
1. 注册时直接指定固定参数值
如果你的deviceIndex是固定不变的(比如总是用设备0),最简单的方式就是在注册服务时,明确告诉Windsor构造函数需要的参数值:
public class YourInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { // 注册FaceDetectionService,并指定构造函数参数 container.Register( Component.For<IFaceDetectionService>() .ImplementedBy<FaceDetectionService>() .WithConstructorArgument("devinceIndex", 0) // 注意参数名要和构造函数里的一致,你这里写的是devinceIndex(可能是拼写错误?) ); // 其他服务和控件的注册... } }
注意:检查构造函数里的参数名是否拼写正确,你代码里写的是
devinceIndex(少了一个i?应该是deviceIndex?),如果注册时参数名和构造函数里的不匹配,也会导致解析失败。如果不想纠结参数名,也可以用参数位置来指定:.WithConstructorArgument(0, 0),第一个0表示构造函数的第一个参数,第二个0是参数值。
2. 从配置文件读取参数值
如果deviceIndex需要灵活配置(比如放在app.config里),可以先读取配置,再传递给Windsor:
public class YourInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { // 从配置文件读取设备索引 int deviceIndex = int.Parse(System.Configuration.ConfigurationManager.AppSettings["FaceDetectionDeviceIndex"]); container.Register( Component.For<IFaceDetectionService>() .ImplementedBy<FaceDetectionService>() .DependsOn(Dependency.OnValue("devinceIndex", deviceIndex)) ); // 其他注册... } }
对应的app.config里要加配置项:
<appSettings> <add key="FaceDetectionDeviceIndex" value="0" /> </appSettings>
3. 用工厂模式处理动态参数
如果每次创建FaceDetectionService都需要不同的deviceIndex(比如支持切换设备),那工厂模式会更合适:
首先定义一个工厂接口:
public interface IFaceDetectionServiceFactory { IFaceDetectionService Create(int deviceIndex); }
然后实现工厂(依赖Windsor的内核来创建服务):
public class FaceDetectionServiceFactory : IFaceDetectionServiceFactory { private readonly IKernel _kernel; public FaceDetectionServiceFactory(IKernel kernel) { _kernel = kernel; } public IFaceDetectionService Create(int deviceIndex) { // 传递动态参数给Windsor解析 return _kernel.Resolve<IFaceDetectionService>(new { devinceIndex = deviceIndex }); } }
最后在安装器里注册工厂和服务:
public class YourInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register( // 注册工厂 Component.For<IFaceDetectionServiceFactory>().ImplementedBy<FaceDetectionServiceFactory>(), // 注册服务本身 Component.For<IFaceDetectionService>().ImplementedBy<FaceDetectionService>() ); // 其他注册... } }
之后在需要使用服务的地方,注入IFaceDetectionServiceFactory,调用Create方法传入对应的deviceIndex即可。
为什么会报错?
Castle Windsor默认会尝试自动解析构造函数的所有参数,但像int这种值类型,Windsor不知道该用什么值来实例化,所以必须明确告诉它参数的来源——要么直接指定值,要么从配置/其他依赖中获取,要么用工厂来动态传递参数。
内容的提问来源于stack exchange,提问作者Ka Res

