【问题标题】:Autofac did not intercept which type of IInterceptorAutofac 没有拦截到哪种类型的 IInterceptor
【发布时间】:2022-05-24 14:58:42
【问题描述】:

我遇到了一个问题,我正在尝试使用 Autofac 记录拦截器。但是 logaspect 没有拦截。确实 aspectInterceptor 选择器在单击添加方法时没有拦截。所以你可以看到我的流程,

看到乔纳森的评论后,我想问是asyc方法的问题吗?

Pogram.cs

public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                .ConfigureContainer<ContainerBuilder>(builder =>
                {
                    builder.RegisterModule(new AutofacResolverModule());
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                })
                .ConfigureLogging(logging =>
                {
                    logging.ClearProviders();
                    logging.SetMinimumLevel(LogLevel.Trace);
                });
    }

//--------

AutofacResolverModule.cs

public class AutofacResolverModule : Module
{
    public AutofacResolverModule()
    {
        
    }
    protected override void Load(ContainerBuilder builder)
    {

        builder.RegisterGeneric(typeof(Repository<,>)).As(typeof(IRepository<,>));
        builder.RegisterGeneric(typeof(BaseService<,,>)).As(typeof(IBaseService<,,>));
        builder.RegisterType<FileLogger>();



        #region AutofacInterceptorHelper
        var assembly = Assembly.GetExecutingAssembly();
        builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces()
            .EnableInterfaceInterceptors(new ProxyGenerationOptions()
            {
                Selector = new AspectInterceptorSelector()
            }).SingleInstance().InstancePerDependency();
        #endregion
    }
}

//---------

AspectInterceptorSelector.cs

public class AspectInterceptorSelector: IInterceptorSelector
    {
        public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors)
        {
            var classAttributes = type.GetCustomAttributes<MethodInterceptorBaseAttribute>(true).ToList();
            var methodAttributes =
                type.GetMethod(method.Name)?.GetCustomAttributes<MethodInterceptorBaseAttribute>(true);
            if (methodAttributes != null)
            {
                classAttributes.AddRange(methodAttributes);
            }

            //classAttributes.Add(new LogAspect(typeof(FileLogger)));

            return classAttributes.OrderBy(x => x.Priority).ToArray();

        }
    }

BaseService.cs

   This class is generic base class and my purpose is all post methods logged into .txt file , is there any problem to use this log aspect into a generic class ?     

public class BaseService<TEntity, TPrimaryKey, TEntityDto> : IBaseService<TEntity, TPrimaryKey, TEntityDto> where TEntity : BaseEntity<TPrimaryKey>, new()
where TEntityDto : IDto
{
    private readonly IRepository<TEntity, TPrimaryKey> _repository;
    private readonly IMapper _mapper;
    public BaseService(IRepository<TEntity, TPrimaryKey> repository, IMapper mapper)
    {
        _repository = repository;
        _mapper = mapper;
    }


   [LogAspect(typeof(FileLogger))]
    public async Task<IResult> Add(TEntityDto entityDto)
    {
        var entity = _mapper.Map<TEntity>(entityDto);
        var result = await _repository.Add(entity);
        return result == null ? new Result(false, ErrorMessages.CreateMessage) : new Result(true, SuccessMessages.CreateMessage, result.Id);


    }


    public async Task<IResult> Find(Expression<Func<TEntity, bool>> predicate)
    {
        var result = await _repository.Find(predicate);
        return result == null ? new Result(true, ErrorMessages.GetMessage) : new Result(true, _mapper.Map<List<ExampleDto>>(result));
    }

    public async Task<IResult> GetAll(Expression<Func<TEntity, bool>> predicate = null)
    {
        var result = predicate == null ? await _repository.GetAll() : await _repository.GetAll(predicate);
        return result == null ? new Result(true, ErrorMessages.GetMessage) : new Result(true, _mapper.Map<List<ExampleDto>>(result));

    }

    public async Task<IResult> HardDelete(TPrimaryKey Id)
    {
        var entity = await _repository.Find(x => x.Id.Equals(Id));
        var result = await _repository.HardDelete(entity);
        return result == 0 ? new Result(false, ErrorMessages.DeleteMessage) : new Result(true, SuccessMessages.DeleteMessage);
    }

    public async Task<IResult> Delete(TPrimaryKey Id)
    {
        var entity = await _repository.Find(x => x.Id.Equals(Id));
        var result = await _repository.Delete(entity);
        return result == 0 ? new Result(false, ErrorMessages.DeleteMessage) : new Result(true, SuccessMessages.DeleteMessage);
    }

    public async Task<IResult> Update(TEntityDto entityDto)
    {
        var entity = _mapper.Map<TEntity>(entityDto);
        var result = await _repository.Update(entity);
        return result == null ? new Result(false, ErrorMessages.UpdateMessage) : new Result(true, SuccessMessages.UpdateMessage, result.Id);
    }
}

LogAspect.cs

public class LogAspect : MethodInterceptor
{
    private readonly LoggerServiceBase _loggerServiceBase;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public LogAspect(Type loggerService)
    {
        if (loggerService.BaseType != typeof(LoggerServiceBase))
        {
            throw new ArgumentException("Wrong Type");
        }

        _loggerServiceBase = (LoggerServiceBase)ServiceTool.ServiceProvider.GetService(loggerService);
        _httpContextAccessor = ServiceTool.ServiceProvider.GetService<IHttpContextAccessor>();
    }

    protected override void OnBefore(IInvocation invocation)
    {
        _loggerServiceBase?.Info(GetLogDetail(invocation));
    }

    private string GetLogDetail(IInvocation invocation)
    {
        var logParameters = new List<LogParameters>();
        for (var i = 0; i < invocation.Arguments.Length; i++)
        {
            logParameters.Add(new LogParameters
            {
                Name = invocation.GetConcreteMethod().GetParameters()[i].Name,
                Value = invocation.Arguments[i],
                Type = invocation.Arguments[i].GetType().Name,
            });
        }

        var logDetail = new LogDetails
        {
            MethodName = invocation.Method.Name,
            Parameters = logParameters,
            User = (_httpContextAccessor.HttpContext == null ||
                    _httpContextAccessor.HttpContext.User.Identity.Name == null)
                ? "?"
                : _httpContextAccessor.HttpContext.User.Identity.Name
        };
        return JsonConvert.SerializeObject(logDetail);
    }
}

MethodInterceptor.cs

 public abstract class MethodInterceptor: MethodInterceptorBaseAttribute
{

    public override void Intercept(IInvocation invocation)
    {
        var isSuccess = true;
        OnBefore(invocation);
        try
        {
            invocation.Proceed();
            var result = invocation.ReturnValue as Task;
            result?.Wait();
        }
        catch (Exception e)
        {
            isSuccess = false;
            OnException(invocation, e);
            throw;
        }
        finally
        {
            if (isSuccess)
            {
                OnSuccess(invocation);
            }
        }

        OnAfter(invocation);
    }

    protected virtual void OnBefore(IInvocation invocation)
    {
    }

    protected virtual void OnAfter(IInvocation invocation)
    {
    }

    protected virtual void OnException(IInvocation invocation, Exception e)
    {
    }

    protected virtual void OnSuccess(IInvocation invocation)
    {
    }
}

MethodInterceptorBaseAttribute.cs

 [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method , AllowMultiple = true,Inherited = true)]
    public abstract class MethodInterceptorBaseAttribute:Attribute, IInterceptor
    {
        public int Priority { get; set; }
        public virtual void Intercept(IInvocation invocation)
        {
            
        }
    }

所以我将近一个月都找不到这个解决方案,有什么想法吗?

【问题讨论】:

  • 我没有专门查看您的问题,但是您是否阅读过有关异步的 DynamicProxy 文档?您可能对代码何时运行做出了错误的假设,DynamicProxy 只会看到您的异步方法被编译器拆分为多个方法。 github.com/castleproject/Core/blob/master/docs/…
  • Jonathon 我不确定动态代理是不是问题,也许我有点不知道但你能对我更特别吗?
  • 很遗憾,不,我不使用 Autofac,只是想让您了解 DP 文档,因为异步拦截捕获了大多数人。不幸的是,您的问题不太可能得到答案,因为有很多部分需要理解。如果可以,请将您的问题细化到最低限度以重现。
  • 我同意早期的 cmets:异步可能是问题的一部分,但是,这需要减少到更小的重现。尝试不使用选择器。尝试不进行装配扫描。在被拦截的类上只尝试一种方法。尝试使用更简单的拦截器。很少有人有时间尝试调试这种复杂性——我知道我没有。

标签: dependency-injection autofac aop castle-dynamicproxy autofac-module


【解决方案1】:

塔里克。在我看来,你的错是没有将泛型类型注册到程序集配置中。您应该在 AutofacResolverModule.cs 中注册泛型类型

builder.RegisterAssemblyOpenGenericTypes(assembly).AsImplementedInterfaces()
        .EnableInterfaceInterceptors(new ProxyGenerationOptions()
        {
            Selector = new AspectInterceptorSelector()
        }).SingleInstance().InstancePerDependency();

【讨论】:

    猜你喜欢
    • 2011-02-26
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    相关资源
    最近更新 更多