【问题标题】:.Net core, Service Collection - class implements multiple generic interfaces.Net core, Service Collection - 类实现多个通用接口
【发布时间】:2021-11-18 22:35:17
【问题描述】:

有一个接口继承了另一个接口

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 的对象相同。

谢谢,

【问题讨论】:

    标签: c# .net-core dependency-injection


    【解决方案1】:

    使用 MS.DI,您在进行如下注册时很容易遇到所谓的Torn Lifestyle 问题:

    // Bad idea: don't do this!
    services.AddSingleton<C<X>>();
    services.AddSingleton<IB<X>, C<X>>();
    services.AddSingleton<IA<X>, C<X>>();
    

    这三个注册导致C&lt;X&gt; 的三个单独注册,这导致三个单独的实例。这个问题被称为撕裂的生活方式。

    相反,无论您是通过其IA&lt;X&gt;IB&lt;X&gt; 接口请求它,还是直接通过C&lt;X&gt; 的具体类型请求它,您都希望能够始终独立地解析C&lt;X&gt; 的同一个实例.

    使用 MS.DI 实现此目的的方法是让两个注册将解析重定向到第三个注册。例如:

    services.AddSingleton<C<X>>();
    services.AddSingleton<IA<X>>(
        c => c.GetRequiredService<C<X>>());
    services.AddSingleton<IB<X>>(
        c => c.GetRequiredService<C<X>>());
    

    不幸的是,这种解决方案有其局限性,尤其是在使用泛型类型时。由于您的 C&lt;T&gt; 是一个泛型类型,您可能希望能够将 T 替换为任何合适的类型,而不必显式地为所有这些类型进行所有注册。

    MS.DI 通过进行如下注册来允许这种情况:

    services.AddSingleton(typeof(IA<>), typeof(C<>));
    

    当请求IA&lt;T&gt; 的任意关闭版本时,此注册允许解析C&lt;T&gt; 的任意关闭版本。换句话说,当请求IA&lt;Person&gt; 时,您将获得C&lt;Person&gt; 的单个实例。这是自动注册的一种形式,它允许通过一次注册来解析多种类型。

    但现在麻烦开始了,因为使用 MS.DI,不可能将防止 Torn Lifestyle 问题的第一种方法与后一种自动注册方法集成在一起。这是因为,对于 MS.DI,防止 Torn Lifestyle 问题的唯一方法是使用委托进行注册。但是没有 AddSingleton(Type, Func&lt;IServiceProvider, Object&gt;) 重载可以实现这一点,据我所知,不可能在 MS.DI 之上构建这样的功能。

    这意味着在防止 Torn Lifestyles 用于开放通用注册时,MS.DI 没有合适的解决方案。我能想到两种解决方法:要么手动进行所有封闭式注册,要么将C&lt;T&gt; 的使用及其接口隐藏在代理或外观后面。然而,它的外观很大程度上取决于您的设计,因此不可能更具体地说明这一点。

    【讨论】:

      猜你喜欢
      • 2020-09-27
      • 1970-01-01
      • 1970-01-01
      • 2018-07-28
      • 2019-03-22
      • 2012-07-23
      • 2022-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多