有一个接口继承了另一个接口
interface IA<T> {}
interface IB<T> : IA<T> {}
和实现IB
的类class C<T>: IB<T> {}
我使用。net核心服务集合来设置IoC。例如:
services.AddSingleton<IB<T>, C<T>>();
我正试图找到一个解决方案来自动注册IA到C和解析IA的实例,IB目标到相同的C的对象
谢谢,
使用MS.DI,当您按照以下方式进行注册时,您很容易遇到所谓的撕裂生活方式问题:
// Bad idea: don't do this!
services.AddSingleton<C<X>>();
services.AddSingleton<IB<X>, C<X>>();
services.AddSingleton<IA<X>, C<X>>();
这三个注册导致C<X>
的三个单独注册,从而导致三个单独的实例。这个问题被称为生活方式的扭曲。
相反,无论您是通过IA<X>
或IB<X>
接口请求它,还是直接通过C<X>
的具体类型请求它,您都希望能够始终独立地解析同一个C<X>
的单个实例。
services.AddSingleton<C<X>>();
services.AddSingleton<IA<X>>(
c => c.GetRequiredService<C<X>>());
services.AddSingleton<IB<X>>(
c => c.GetRequiredService<C<X>>());
不幸的是,这个解决方案有其局限性,特别是在处理泛型类型时。由于C<T>
是泛型类型,您可能希望能够将T
替换为任何合适的类型,而不必显式地为所有这些类型进行所有注册。
。DI通过进行如下注册来实现此场景:
services.AddSingleton(typeof(IA<>), typeof(C<>));
此注册允许在请求IA<T>
的任意封闭版本时解析C<T>
的任意封闭版本。换句话说,当请求IA<Person>
时,您将获得C<Person>
的单个实例。这是自动注册的一种形式,它允许通过一次注册来解析许多类型。
但是现在麻烦开始了,因为使用MS.DI,不可能将防止撕裂生活方式问题的第一种方法与后一种自动注册方法集成在一起。这是因为,使用MS.DI,防止"生活方式撕裂"问题的唯一方法是使用委托进行注册。但是没有AddSingleton(Type, Func<IServiceProvider, Object>)
过载可以实现这一点,而且据我所知,在MS.DI之上构建这样的功能是不可能的。
这意味着当涉及到防止开放通用注册的Torn Lifestyles时,MS.DI没有合适的解决方案。我能想到的解决方法有两种:要么手动完成所有的关闭注册,要么将C<T>
及其接口的使用隐藏在代理或facade后面。然而,这看起来如何,高度依赖于你的设计,所以不可能更具体。