Catel IoC容器泛型解析异常:PluginWrapper无法实例化问题排查
关于Catel IoC容器解析PluginWrapper泛型类的问题
场景与问题
现有一个带有插件架构的程序,原插件类要求具备无参构造函数,现在希望插件开发者可通过构造函数参数声明依赖程序基础设施,内部通过泛型类PluginWrapper<TImpl>封装插件类,使其表现得像插件时代前的内部类。
相关代码定义
基础设施
public interface IInfrastructure { } public class Infrastructure : IInfrastructure { }
插件接口
public interface IPlugin { }
依赖基础设施的插件实现
public class Plugin : IPlugin { public Plugin(IInfrastructure _) { } }
泛型包装类
public class PluginWrapper<TImpl> where TImpl: class, IPlugin { public PluginWrapper(TImpl _) { } }
注册与解析情况
注册代码如下:
ServiceLocator.Default.RegisterType<IInfrastructure, Infrastructure>(RegistrationType.Transient); ServiceLocator.Default.RegisterType(typeof(Plugin),typeof(Plugin), RegistrationType.Transient); var wrapperType = typeof(PluginWrapper<>).MakeGenericType(typeof(Plugin)); ServiceLocator.Default.RegisterType(wrapperType, wrapperType,RegistrationType.Transient);
- 可成功解析插件类型:
Assert.NotNull(ServiceLocator.Default.ResolveType<Plugin>()); - 无法解析包装器类型:
Assert.NotNull(ServiceLocator.Default.ResolveType<PluginWrapper<Plugin>>());
疑问:这是Catel IoC容器的限制,还是操作有误?
解决方案
这是注册方式操作有误,并非Catel IoC容器的限制。问题出在你注册的是PluginWrapper<Plugin>这个封闭泛型类型,但容器无法自动关联到已注册的Plugin实例作为构造函数参数。可以通过以下两种方式解决:
方式1:注册开放泛型定义(推荐)
直接注册PluginWrapper<>的开放泛型类型,容器会自动为所有符合约束的TImpl类型处理依赖注入:
ServiceLocator.Default.RegisterType<IInfrastructure, Infrastructure>(RegistrationType.Transient); ServiceLocator.Default.RegisterType(typeof(Plugin), typeof(Plugin), RegistrationType.Transient); // 注册开放泛型,而非具体封闭类型 ServiceLocator.Default.RegisterType(typeof(PluginWrapper<>), typeof(PluginWrapper<>), RegistrationType.Transient);
注册完成后,直接解析PluginWrapper<Plugin>即可成功获取实例。
方式2:手动指定构造参数(适合必须注册封闭类型的场景)
如果需要注册具体的PluginWrapper<Plugin>封闭类型,需在注册时手动提供构造函数所需的Plugin实例:
ServiceLocator.Default.RegisterType<IInfrastructure, Infrastructure>(RegistrationType.Transient); ServiceLocator.Default.RegisterType(typeof(Plugin), typeof(Plugin), RegistrationType.Transient); var wrapperType = typeof(PluginWrapper<>).MakeGenericType(typeof(Plugin)); ServiceLocator.Default.RegisterType(wrapperType, wrapperType, RegistrationType.Transient, () => Activator.CreateInstance(wrapperType, ServiceLocator.Default.ResolveType<Plugin>()) );
内容的提问来源于stack exchange,提问作者Patrick Kursawe
相关产品推荐
相关产品推荐

