我的应用程序包含许多通用ICommandHandler<TRequest, TResponse>
接口的非泛型实现。我试图通过调用EnableInterfaceInterceptors
向他们添加拦截器。但是当我尝试解析命令处理程序时,Autofac会抛出一个异常,并显示以下消息:
OwnedByLifetimeScope无法使用接口拦截,因为它提供的服务不是公开可见的接口。检查组件的注册,以确保您没有启用拦截并将其注册为内部/专用接口类型。
这是我的注册和解析器代码。我如何使用泛型类型的拦截器并解决它?
builder.RegisterAssemblyTypes(assemblyType.Assembly)
.AsClosedTypesOf(typeof(ICommandHandler<,>))
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(LoggingInterceptor))
.InterceptedBy(typeof(ExceptionHandlingInterceptor))
.InstancePerLifetimeScope();
This is resolver
public class CommandResolver : ICommandBus
{
private readonly ILifetimeScope _lifetimeScope;
public CommandResolver(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
}
public TResult Execute<TResult>(ICommand<TResult> command)
{
var generic = typeof(ICommandHandler<,>);
var genericArgumentList = new Type[]
{
command.GetType(), typeof(TResult)
};
var commandHandlerType = generic.MakeGenericType(genericArgumentList);
// Exception is thrown here
var handler = (ICommandHandler)_lifetimeScope.Resolve(commandHandlerType);
return (TResult)handler.Execute(command);
}
}
修改 我在其他接口上使用这个拦截器。在CommandResolver中没有拦截器的情况下工作得很好。当我试图拦截ICommandHandler&lt;,&gt;时,它不起作用。我没有在这里写拦截器registring代码,正如我所说,它适用于其他接口,例如在ICommandBus上。没有任何私人或内部接口,我之前已经检查过。
答案 0 :(得分:1)
实际上,这里的问题是AsClosedTypesOf()
将服务注册为具体类和封闭接口-因为它们都是所提供接口的封闭类型。
只要您仅通过接口进行解析,就可以通过将扩展名AsClosedTypesOf()
修改为仅注册接口类型来解决此问题。
/// <summary>
/// Specifies that a type from a scanned assembly is registered if it implements an interface
/// that closes the provided open generic interface type.
/// </summary>
/// <typeparam name="TLimit">Registration limit type.</typeparam>
/// <typeparam name="TScanningActivatorData">Activator data type.</typeparam>
/// <typeparam name="TRegistrationStyle">Registration style.</typeparam>
/// <param name="registration">Registration to set service mapping on.</param>
/// <param name="openGenericServiceType">The open generic interface or base class type for which implementations will be found.</param>
/// <returns>Registration builder allowing the registration to be configured.</returns>
public static IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle> AsClosedInterfacesOf<TLimit, TScanningActivatorData, TRegistrationStyle>(this IRegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle> registration, Type openGenericServiceType) where TScanningActivatorData : ScanningActivatorData
{
if ((object)openGenericServiceType == null)
throw new ArgumentNullException(nameof(openGenericServiceType));
if (!openGenericServiceType.IsInterface)
throw new ArgumentException("Generic type must be an interface", nameof(openGenericServiceType));
return registration
.Where(candidateType => candidateType.IsClosedTypeOf(openGenericServiceType))
.As(candidateType =>
candidateType.GetInterfaces()
.Where(i => i.IsClosedTypeOf(openGenericServiceType))
.Select(t => (Service)new TypedService(t)));
}
然后您可以将注册更改为
builder.RegisterAssemblyTypes(assemblyType.Assembly)
.AsClosedInterfacesOf(typeof(ICommandHandler<,>))
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(LoggingInterceptor))
.InterceptedBy(typeof(ExceptionHandlingInterceptor))
.InstancePerLifetimeScope();
答案 1 :(得分:0)
看来你发现了一个错误!我filed an issue with the Autofac.Extras.DynamicProxy repository on your behalf我已经在这个问题中加入了一个完整的复制品。你可以在那里订阅。
我们可以很快解决这个问题,但是,如果你的PR有分辨率,它可能会更快。
很抱歉,这不是你可能希望的答案,但至少这是一个答案。