我有以下内容,它们被打包成一个纽吉特包裹

// Internal implementation 

internal interface ICoreService
{
  int GetSomething();
}

internal class CoreService : ICoreService
{
  int ICoreService.GetSomething()
  {
     return 2;
  }
}

// Exposed Service

public interface IExposedService
{
  int GetNumber();
}

public class ExposedService: IExposedService
{
  private readonly ICoreService _coreService;
  
  internal ExposedService(ICoreService coreService)
  {
     _coreService = coreService;
  }

  public int GetNumber()
  {
     return _coreService.GetSomething();
  }
}

IServiceCollection有两个扩展方法

public static IServiceCollection Initialize(this IServiceCollection services)
{
   services.AddSingleton<ICoreService, CoreService>();

   return services;
}

public static IServiceCollection AddExposedService(this IServiceCollection services)
{
   services.AddTransient<IExposedService, ExposedService>();

   return services;
}

它们被链接在一起,例如:builder.Services.Initialize().AddExposedService().

现在的问题是,由于ICoreService是内部的,当将这个包添加到另一个应用程序时,DI无法解析ICoreService并将其注入ExposedService.

但如果我做了以下几点,它就可以正常工作了:

public static IServiceCollection Initialize(this IServiceCollection services)
{
   services.AddSingleton<ICoreService, CoreService>();

   return services;
}

public static IServiceCollection AddExposedService(this IServiceCollection services)
{
   services.AddTransient<IExposedService>(sp =>
   {
      var coreService = sp.GetRequiredService<ICoreService>();

      return new ExposedService(coreService)
   });

   return services;
}

这样做的目的是隐藏CoreService,以便在添加包时不能将ICoreService注入任何您想要的东西.

问题是:这种解决ICoreService并使用穷人的DI的方法是常见的吗?如果不是,你还能怎么做呢?此外,在幕后发生了什么,使得这种方法能够奏效?

推荐答案

在测试您的第一个方法时,我遇到了以下错误.由于您尚未提供任何错误详细信息,因此我在此与您分享,以澄清问题.请确认这与您遇到的错误相同.

System.InvalidOperationException: "A suitable constructor for type 'Package.A.ExposedService' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor."

Understanding the Error:

当依赖项注入框架不能直接创建ExposedService类的实例时,通常是因为它的构造函数被标记为internal,就会出现这个错误.依赖项注入框架需要公共构造函数来实例化和管理类的依赖项.

Your provided Solution:

您使用工厂委托的解决方案是完全正确的!以下是它的工作原理:

services.AddTransient<IExposedService>(sp =>
{
    var coreService = sp.GetRequiredService<ICoreService>();
    return new ExposedService(coreService); 
});
  • Bypassing Restrictions:此技术绕过了internal个构造函数的限制.委托为依赖项注入框架提供了实例化ExposedService个实例的方法.

  • Encapsulation Preserved:重要的是,这种方法不会影响封装.Package A的内部详细信息保持受保护,而您只公开IExposedService接口.

我希望这会有帮助,如果你有任何进一步的问题,请告诉我.

Csharp相关问答推荐

Microsoft. SQLServer. Types(106.1000.6)在try 从用户定义的类型检索值时引发异常

应该使用哪一个?"_counter += 1 OR互锁增量(ref_counter)"""

.NET 8 Web-API返回空列表

ASP.NET Core AutoMapper:如何解决错误 CS0121调用在以下方法或属性之间不明确

在此系统上已禁用获取正在运行的脚本.&在ASP.NET Core Web API中

C#无法让WinForm进度条生成动画错误跨线程操作无效

关于扩展文件类C#的矛盾

在C#中过滤Excel文件

Regex字母数字校验

MSTest--将消息直接写入StdOut和使用TestContext有什么不同?

C#多键字典和TryGetValue

在C#ASP.NET内核中使用INT AS-1进行控制器场景的单元测试

JsonPath在Newtonsoft.Json';S实现中的赋值

ASP.NET MVC数据批注验证组复选框

C#如何获取字符串中引号之间的文本?

Visual Studio,Docker容器-容器调用:连接被拒绝

Xamarin中出错.表单:应用程序的分部声明不能指定不同的基类

使用C#代码和SQL SERVER中的相同证书签名会产生不同的结果

CsvHelper在第二次迭代时抛出System.ObjectDisposedException

如何在flutter dart中使用publicKey.xml文件进行rsa加密,我遇到了问题Exception:Could not parse BigInt