我有一项自定义服务,其中我使用的是 Microsoft 的
IDataProtector
。
我已在启动时使用 AddScoped
注册了我的服务,但使用 IDataProtector
时遇到问题。
错误信息:
尝试激活“服务”时无法解析类型“Microsoft.AspNetCore.DataProtection.IDataProtector”的服务。
这是我的代码:
public class Service: IInjectable
{
private readonly IDataProtector _protector;
public Service(IDataProtector protector)
{
_protector = protector.CreateProtector("key");
}
other code ...
}
我注册服务的方式:
public static void RegisterScoped<T>(
this IServiceCollection services, params Assembly[] assemblies)
{
IEnumerable<Type> types = assemblies.SelectMany(a => a.GetExportedTypes())
.Where(c => c.IsClass && typeof(T).IsAssignableFrom(c));
foreach (var item in types)
services.AddScoped(item);
}
启动:
services.RegisterScoped<IInjectable>(typeof(IInjectable).Assembly);
终于,我发现问题了:
我必须在我的服务构造函数中使用 IDataProtectionProvider 而不是 IDataProtector
有一天我也遇到了同样的情况,不得不在汇编中查看类
AddDataProtection()
的类方法DataProtectionServiceCollectionExtensions
的源代码Microsoft.AspNetCore.DataProtection.dll
。
对于那些对 DataProtection 服务的注册细节感兴趣的人,这是实际神奇发生的代码摘录:
private static void AddDataProtectionServices(IServiceCollection services)
{
if (OSVersionUtil.IsWindows())
{
// Assertion for platform compat analyzer
Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
services.TryAddSingleton<IRegistryPolicyResolver, RegistryPolicyResolver>();
}
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IConfigureOptions<KeyManagementOptions>, KeyManagementOptionsSetup>());
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPostConfigureOptions<KeyManagementOptions>, KeyManagementOptionsPostSetup>());
services.TryAddEnumerable(
ServiceDescriptor.Transient<IConfigureOptions<DataProtectionOptions>, DataProtectionOptionsSetup>());
services.TryAddSingleton<IKeyManager, XmlKeyManager>();
services.TryAddSingleton<IApplicationDiscriminator, HostingApplicationDiscriminator>();
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, DataProtectionHostedService>());
// Internal services
services.TryAddSingleton<IDefaultKeyResolver, DefaultKeyResolver>();
services.TryAddSingleton<IKeyRingProvider, KeyRingProvider>();
services.TryAddSingleton<IDataProtectionProvider>(s =>
{
var dpOptions = s.GetRequiredService<IOptions<DataProtectionOptions>>();
var keyRingProvider = s.GetRequiredService<IKeyRingProvider>();
var loggerFactory = s.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
IDataProtectionProvider dataProtectionProvider = new KeyRingBasedDataProtectionProvider(keyRingProvider, loggerFactory);
// Link the provider to the supplied discriminator
if (!string.IsNullOrEmpty(dpOptions.Value.ApplicationDiscriminator))
{
dataProtectionProvider = dataProtectionProvider.CreateProtector(dpOptions.Value.ApplicationDiscriminator);
}
return dataProtectionProvider;
});
services.TryAddSingleton<ICertificateResolver, CertificateResolver>();
}
正如您在这里看到的,只有
IDataProtectionProvider
在services.TryAddSingleton<IDataProtectionProvider>
行中注册,没有任何提及IDataProtector
。