使用Decor.NET结合Func依赖注入时无法实例化代理类的问题
使用Decor.NET结合带Func的Transient依赖注入时的构造函数异常解决办法
问题场景
当服务以单例作用域注册且不使用Func时,Decor.NET能正常工作:
services.AddDecor().AddTransient<CacheDecorator>().AddTransient<CacheTestBLL>().Decorated();
但注册带Func的Transient服务时,调用GetService()会抛出以下异常:
Can not instantiate proxy of class: MyApp.Implementations.CompanyTest2BLL. Could not find a parameterless constructor. (Parameter 'constructorArguments')' MissingMethodException: Constructor on type 'Castle.Proxies.CompanyTest2BLLProxy' not found.
Decor.NET底层依赖Castle DynamicProxy,问题根源在于Castle无法自动匹配被装饰类的构造函数参数,导致代理类生成失败。
解决办法
1. 确保构造参数可被DI容器自动解析
如果CompanyTest2BLL的构造函数依赖其他服务,先确认这些服务已经在DI容器中完成注册。比如构造函数依赖IDependency,需要先注册:
services.AddTransient<IDependency, DependencyImpl>();
2. 显式通过工厂方法传递构造参数
当使用Func创建实例时,需要在注册时明确写出实例创建逻辑,让Decor.NET能正确传递参数给Castle代理:
services.AddDecor() .AddTransient<CacheDecorator>() .AddTransient(sp => { // 从容器获取构造所需的依赖 var requiredDep = sp.GetRequiredService<IDependency>(); // 手动实例化被装饰类,传递参数 return new CompanyTest2BLL(requiredDep); }) .Decorated();
3. 临时添加无参构造函数(不推荐)
如果只是临时调试,可以给CompanyTest2BLL添加无参构造函数,但这会违背依赖注入的设计原则,可能导致实例状态异常,不建议在生产环境使用:
public class CompanyTest2BLL { // 临时无参构造 public CompanyTest2BLL() { } // 正常业务构造函数 public CompanyTest2BLL(IDependency dependency) { // 初始化逻辑 } }
4. 自定义Castle代理的构造函数选择逻辑
如果需要更精细的控制,可以配置Decor.NET的ProxyGeneratorOptions,自定义构造函数选择规则:
// 自定义构造选择器 public class CustomConstructorSelector : IConstructorSelector { public ConstructorInfo SelectConstructor(Type type, ConstructorInfo[] constructors) { // 选择需要的构造函数,比如参数最多的那个 return constructors.OrderByDescending(c => c.GetParameters().Length).First(); } } // 注册时配置 services.AddDecor(options => { options.ProxyGeneratorOptions = new ProxyGeneratorOptions { Selector = new CustomConstructorSelector() }; }) .AddTransient<CacheDecorator>() .AddTransient<CompanyTest2BLL>() .Decorated();
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

