提问人:Dark_Knight 提问时间:11/4/2023 最后编辑:Dark_Knight 更新时间:11/6/2023 访问量:59
Autofac 无法解析类型为“log4net”的服务。ILog'
Autofac Unable to resolve service for type 'log4net.ILog'
问:
我有 ASP.NET 运行良好的 MVC 应用程序,但是一旦我升级了 Autofac 并对 Log4Net 中间件示例进行了更改,如果我尝试解决 ILog,它就会不断失败。
我们使用,我正在得到FluentMigrator
无法解析类型为“log4net”的服务。ILog“,同时尝试 激活“Migrations.Maintenance.BeforeAll.FlushRedisOnVersionUpdate”。
中间件似乎无法解析 log4net。ILog,它注入到构造函数中。
internal class OrderedMaintenanceLoader : IMaintenanceLoader
{
#region Private fields
private readonly IMaintenanceLoader _inner;
private readonly CurrentReleaseMigrationStage _releaseMigrationStage;
#endregion
#region Ctors
public OrderedMaintenanceLoader(IMaintenanceLoader inner, CurrentReleaseMigrationStage releaseMigrationStage)
{
_inner = inner ?? throw new ArgumentNullException(nameof(inner));
_releaseMigrationStage = releaseMigrationStage ?? throw new ArgumentNullException(nameof(releaseMigrationStage));
}
#endregion
#region IMaintenanceLoader Members
public IList<IMigrationInfo> LoadMaintenance(MigrationStage stage)
{
return _inner.LoadMaintenance(stage)
.Where(info => _releaseMigrationStage.CanExecuteMaintenanceMigration(info.Migration))
.OrderBy(
info =>
{
OrderedMaintenanceAttribute orderedMaintenanceAttribute = info.Migration.GetType().GetCustomAttribute<OrderedMaintenanceAttribute>();
return orderedMaintenanceAttribute?.Order ?? int.MaxValue;
})
.ToList();
}
#endregion
}
以下是注册的一部分(有很多注册正在发生):
var loggerMiddlewareModule = new MiddlewareModule(new Log4NetMiddleware());
builder.RegisterModule(loggerMiddlewareModule);
builder.RegisterType<LoggerAdapterProvider>().As<ILoggerProvider>().InstancePerLifetimeScope();
builder.RegisterType<LoggerFactory>().As<ILoggerFactory>().InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).InstancePerLifetimeScope();
// registers AutofacServiceProvider and AutofacServiceScopeFactory
builder.Populate(Enumerable.Empty<ServiceDescriptor>());
builder.RegisterType<AssemblyFileLoadEngine>().As<IAssemblyLoadEngine>().InstancePerLifetimeScope();
builder.RegisterType<MaintenanceLoader>();
builder.Register(context => new OrderedMaintenanceLoader(context.Resolve<IMaintenanceLoader>(), context.Resolve<CurrentReleaseMigrationStage>()))
.As<IMaintenanceLoader>()
.InstancePerLifetimeScope();
builder
.RegisterType<AssemblySource>()
.Keyed<IAssemblySource>(AssemblySourceKey)
.InstancePerLifetimeScope();
builder
.Register<IAssemblySource>(
ctx =>
new MaintenanceAssemblySource(ctx.ResolveKeyed<IAssemblySource>(AssemblySourceKey)))
.As<IAssemblySource>()
.InstancePerLifetimeScope();
这是在构造函数中失败的迁移类:
[OrderedMaintenance(MigrationStage.BeforeAll, 5)]
public class FlushRedisOnVersionUpdate : ConditionalMigration
{
#region Private fields
private readonly IConfigurationStateMonitor _configurationStateMonitor;
private readonly ILog _logger;
#endregion
#region Ctors
public FlushRedisOnVersionUpdate(
IConfigurationStateMonitor configurationStateMonitor,
ILog logger) : base(migrationProcessor)
{
_configurationStateMonitor = configurationStateMonitor;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
#endregion
#region Overrides
public override void Up()
{
_configurationStateMonitor.FlushCache();
}
#endregion
}
这是运行迁移的类:
public class MigrationService : IMigrationService
{
#region Private fields
private readonly ILog _logger;
private readonly DatabaseOptions _databaseOptions;
private readonly MigrationManagerOptions _migrationOptions;
private readonly ILifetimeScope _scope;
#endregion
#region Ctors
public MigrationService(
DatabaseOptions databaseOptions,
MigrationManagerOptions migrationOptions,
ILog logger,
ILifetimeScope scope)
{
_databaseOptions = databaseOptions;
_migrationOptions = migrationOptions;
_scope = scope;
_logger = logger;
}
#endregion
#region Private methods
private ILifetimeScope BeginLifetimeScope(PackageDefinition package, Release release, ReleaseMigrationStage releaseMigrationStage)
{
return _scope.BeginLifetimeScope(
builder =>
{
builder
.RegisterModule<MicrosoftExtensionsOptionsModule>();
builder
.Configure<ProcessorOptions>(
options =>
{
options.ConnectionString = _databaseOptions.ConnectionString;
options.Timeout = TimeSpan.FromMinutes(_migrationOptions.DefaultMigrationCommandTimeout);
});
builder.RegisterInstance(new CurrentReleaseMigrationStage(releaseMigrationStage));
builder.RegisterInstance(package);
builder.RegisterInstance(new CurrentRelease(release));
});
}
#endregion
#region IMigrationService Members
public bool Migrate(PackageDefinition package, Release release, ReleaseMigrationStage releaseMigrationStage)
{
using (ILifetimeScope scope = BeginLifetimeScope(package, release, releaseMigrationStage))
{
bool hasAnyToApply = scope.Resolve<TaskExecutor>().HasMigrationsToApply();
scope.Resolve<IMigrationRunner>().MigrateUp();
return hasAnyToApply;
}
}
#endregion
}
MigrationService
实际上可以得到ILog ...可能是因为我们创建了一个生命周期范围的问题?
更新:
我已经创建了一个单元测试,但没有调用并且仍然失败(所以问题不在创建生命周期范围中):MigrationService
这是例外:
System.Reflection.TargetInvocationException
HResult=0x80131604
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) in f:\dd\ndp\clr\src\BCL\system\reflection\methodinfo.cs:line 761
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in f:\dd\ndp\clr\src\BCL\system\reflection\methodinfo.cs:line 739
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) in f:\dd\ndp\clr\src\BCL\system\reflection\methodbase.cs:line 211
at NUnit.Framework.Internal.Reflect.InvokeMethod(MethodInfo method, Object fixture, Object[] args) in C:\Src\NUnit\nunit\src\NUnitFramework\framework\Internal\Reflect.cs:line 222
This exception was originally thrown at this call stack:
Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(System.IServiceProvider) in ActivatorUtilities.cs
Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(System.IServiceProvider, System.Type, object[]) in ActivatorUtilities.cs
FluentMigrator.Runner.MaintenanceLoader..ctor.AnonymousMethod__4(<>f__AnonymousType3<System.Type, FluentMigrator.MigrationStage?>)
System.Linq.Enumerable.WhereSelectEnumerableIterator<TSource, TResult>.MoveNext() in Enumerable.cs
System.Linq.Lookup<TKey, TElement>.Create<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource, TKey>, System.Func<TSource, TElement>, System.Collections.Generic.IEqualityComparer<TKey>) in Lookup.cs
System.Linq.GroupedEnumerable<TSource, TKey, TElement>.GetEnumerator() in GroupedEnumerable.cs
System.Linq.Enumerable.ToDictionary<TSource, TKey, TElement>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource, TKey>, System.Func<TSource, TElement>, System.Collections.Generic.IEqualityComparer<TKey>) in Enumerable.cs
FluentMigrator.Runner.MaintenanceLoader.MaintenanceLoader(FluentMigrator.Runner.Initialization.IAssemblySource, Microsoft.Extensions.Options.IOptions<FluentMigrator.Runner.Initialization.RunnerOptions>, FluentMigrator.Runner.IMigrationRunnerConventions, System.IServiceProvider) in MaintenanceLoader.cs
Autofac.Core.Activators.Reflection.BoundConstructor.Instantiate() in BoundConstructor.cs
Inner Exception 1:
DependencyResolutionException: An exception was thrown while activating λ:System.Object -> FluentMigrator.Runner.MaintenanceLoader.
Inner Exception 2:
DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor(FluentMigrator.Runner.Initialization.IAssemblySource, Microsoft.Extensions.Options.IOptions`1[FluentMigrator.Runner.Initialization.RunnerOptions], FluentMigrator.Runner.IMigrationRunnerConventions, System.IServiceProvider)' on type 'MaintenanceLoader'.
Inner Exception 3:
InvalidOperationException: Unable to resolve service for type 'log4net.ILog' while attempting to activate 'Migrations.Maintenance.BeforeAll.FlushRedisOnVersionUpdate'.
下面是测试用例:
[TestCase(4, typeof(FlushRedisOnVersionUpdate), Description = "FlushRedisOnVersionUpdate should run after RemoveBuilderEntityPropertiesMigration")]
public void BeforeAllMigrationsShouldRunInSpecifiedOrder(int order, Type expectedMigrationType)
{
using (IContainer container = BuildContainer())
{
IMaintenanceLoader maintenanceLoader = container.Resolve<IMaintenanceLoader>();
IList<IMigrationInfo> beforeAllMigrations = maintenanceLoader.LoadMaintenance(MigrationStage.BeforeAll);
Assert.IsNotNull(beforeAllMigrations);
Assert.Less(order, beforeAllMigrations.Count);
Assert.IsInstanceOf(expectedMigrationType, beforeAllMigrations[order].Migration);
}
}
它失败IMaintenanceLoader maintenanceLoader = container.Resolve<IMaintenanceLoader>();
我还更改了注册以使用装饰器注册,但结果相同。
builder.RegisterType<MaintenanceLoader>()
.Keyed<IMaintenanceLoader>(DecorateWithEx)
.UsingConstructor(typeof(IAssemblySource),
typeof(IOptions<RunnerOptions>),
typeof(IMigrationRunnerConventions),
typeof(IServiceProvider));
builder
.RegisterType<OrderedMaintenanceLoader>()
.As<IOrderedMaintenanceLoader>();
builder
.RegisterDecorator<IMaintenanceLoader>((ctx, maintenanceLoader) =>
ctx.Resolve<IOrderedMaintenanceLoader>(TypedParameter.From(maintenanceLoader)), DecorateWithEx)
.InstancePerLifetimeScope();
答:
0赞
Mark Seemann
11/4/2023
#1
这是 OP 中发布的注册码:
builder.RegisterType<LoggerAdapterProvider>().As<ILoggerProvider>().InstancePerLifetimeScope();
builder.RegisterType<LoggerFactory>().As<ILoggerFactory>().InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Logger<>)).As(typeof(ILogger<>)).InstancePerLifetimeScope();
// registers AutofacServiceProvider and AutofacServiceScopeFactory
builder.Populate(Enumerable.Empty<ServiceDescriptor>());
builder.RegisterType<AssemblyFileLoadEngine>().As<IAssemblyLoadEngine>().InstancePerLifetimeScope();
builder.RegisterType<MaintenanceLoader>();
builder.Register(context => new OrderedMaintenanceLoader(context.Resolve<IMaintenanceLoader>(), context.Resolve<CurrentReleaseMigrationStage>()))
.As<IMaintenanceLoader>()
.InstancePerLifetimeScope();
这些语句均未注册 。注册服务,或者实现处理它的注册源。ILog
评论
0赞
Dark_Knight
11/4/2023
对不起,我忘了提到我向新中间件注册了日志模块。我将编辑问题。它在那里,但仍然抛出异常
评论