zoukankan      html  css  js  c++  java
  • 动态代理

    反射机制:程序运行时自省的能力,通过反射操作类与对象,获取对象的类定义,类声明的属性与方法,调用方法与构造对象,甚至在运行时修改类的定义。

    动态代理:是一种方便运行时动态构建代理,动态处理代理方法调用机制。代理是对调用目标的一个包装,对目标代码不是直接发生,而是通过代理发生,

    动态代理,很多情况可以看作是装饰器的一个运用,反射是实现的一种常用的方式。

    Autofac与Castle.DynamicProxy实现AOP功能

    1、定义拦截器,实现 Castle.DynamicProxy.IInterceptor 

    public interface IInterceptor
    {
        void Intercept(IInvocation invocation);
    }

    其中:IInvocation的接口的方法,invocation.Arguments是数组,args[0]是第一个参数

    invocation.Proceed(); // 调用下一个拦截器,直到最终的目标方法。

    定义好了拦截器后,如何应用到相关对象呢?有两种方式:

         1)使用 Autofac.Extras.DynamicProxy.InterceptAttribute 特性将拦截器添加到相关的类或接口上;
         2)使用 ContainerBuilder 的 InterceptedBy() 方法在注册对象的同时添加拦截器。
     
    基于接口的拦截器
       在注册对象的同时启用 EnableInterfaceInterceptors() 方法。
    基于类的拦截器

          在注册对象的同时启用 EnableClassInterceptors() 方法。

    比如:注册两个拦截器,然后通过autofac 的Ioc容器,实现Resolve服务,执行顺序:CalculaterInterceptor  --> CalculaterInterceptor2 --> Target Method --> CalculaterInterceptor2 --> CalculaterInterceptor 。拦截器中 invocation.Proceed() 方法用于调用下一个拦截器(若存在),直到最终的目标方法(Target Method)。不过 invocation.Proceed() 并不是一定要调用的,例如,对于有返回值的目标方法,我们在拦截器中设置 invocation.ReturnValue 值就可正确执行,这样便不会执行目标方法。在有些场景中,如身份验证、缓存读取等还是特别有用

     var builder = new ContainerBuilder();
                builder.RegisterType<Calculater>()
                    .As<ICalculater>()
                    .EnableInterfaceInterceptors()
                    .InterceptedBy(typeof(CalculaterInterceptor), typeof(CalculaterInterceptor2));  // 这里定义了两个拦截器,注意它们的顺序
    
                builder.RegisterType<CalculaterInterceptor>();  // 注册拦截器
                builder.RegisterType<CalculaterInterceptor2>();  // 注册拦截器2
    
                var ioc = builder.Build();
    
                var calculater = ioc.Resolve<ICalculater>();
                var addResult = calculater.Add(2, 3);
    
                Console.WriteLine($"add result: {addResult}");

    另外:接口上以特性的形式注册,如上面代码中注释掉的那部分。若是既有在类型上注册,也有在 Autofac 的 Builder 中注册,那么这个拦截器会重复执行。

    非虚方法,所有拦截器不会在该方法中调用。

    在ABP vnext的实现方式,在服务自动注册模块,首先根据 实现类型ImplementationType(是class,不是接口,抽象类,泛型类),检查生命周期、servicesType注册在SerivceCollection里面,OnExposing定义ImplementationType的ExposedTypes,,可自定义委托函数OnRegistred,定义ImplementationType的Interceptors、

    在注入Autofac容器

    AbpAsyncDeterminationInterceptor<>的泛型参数才是用户定义的拦截器, interceptor:IAbpIntercepor

    if (serviceType.IsInterface)
                {
                    registrationBuilder = registrationBuilder.EnableInterfaceInterceptors();
                }
                else
                {
                    (registrationBuilder as IRegistrationBuilder<TLimit, ConcreteReflectionActivatorData, TRegistrationStyle>)?.EnableClassInterceptors();
                }
    
                foreach (var interceptor in interceptors)
                {
                    registrationBuilder.InterceptedBy(
                        typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(interceptor)
                    );
                }

    AsyncDeterminationInterceptor(IAsyncInterceptor) 

    CastleAsyncAbpInterceptorAdapter<TInterceptor>(TInterceptor)需要用户定义的拦截器,的泛型参数, TInterceptor : IAbpInterceptor

    这里有个IAbpMethodInvocation的实现CastleAbpMethodInvocationAdapter(invocation, proceedInfo, proceed),CastleAbpMethodInvocationAdapterWithReturnValue

    https://github.com/JSkimming/Castle.Core.AsyncInterceptor

     

    关于特性

    1、Dependency特性,它拥有ServiceLifeTime,TryRegister,ReplaceServices属性

    ExploseService特性,同时实现IExplosedServiceTypesProvider对外暴露的ServiceTypes类型,是对包括InclueDefault(即包括默认接口,I开头,默认结尾)IncludeSelf( 包括自己)

    type.GetCustomAttribute<DependencyAttribute>(true);
    
     private static readonly ExposeServicesAttribute DefaultExposeServicesAttribute =
                new ExposeServicesAttribute
                {
                    IncludeDefaults = true,
                    IncludeSelf = true
                };
    
            public static List<Type> GetExposedServices(Type type)
            {
                return type
                    .GetCustomAttributes()
                    .OfType<IExposedServiceTypesProvider>()
                    .DefaultIfEmpty(DefaultExposeServicesAttribute)
                    .SelectMany(p => p.GetExposedServiceTypes(type))
                    .ToList();
            }
     public static List<Type> FindDependedModuleTypes(Type moduleType)
            {
                AbpModule.CheckAbpModuleType(moduleType);
    
                var dependencies = new List<Type>();
    
                var dependencyDescriptors = moduleType
                    .GetCustomAttributes()
                    .OfType<IDependedTypesProvider>();
    
                foreach (var descriptor in dependencyDescriptors)
                {
                    foreach (var dependedModuleType in descriptor.GetDependedTypes())
                    {
                        dependencies.AddIfNotContains(dependedModuleType);
                    }
                }
                return dependencies;
            }
    public static UnitOfWorkAttribute GetUnitOfWorkAttributeOrNull(getmethodInfo)
            {
                var attrs = methodInfo.GetCustomAttributes(true).OfType<UnitOfWorkAttribute>().ToArray();
                if (attrs.Length > 0)
                {
                    return attrs[0];
                }
    
                attrs = methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes(true).OfType<UnitOfWorkAttribute>().ToArray();
                if (attrs.Length > 0)
                {
                    return attrs[0];
                }
                
                return null;
            }
            
            private static bool AnyMethodHasUnitOfWorkAttribute(TypeInfo implementationType)
            {
                return implementationType
                    .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                    .Any(HasUnitOfWorkAttribute);
            }
    
            private static bool HasUnitOfWorkAttribute(MemberInfo methodInfo)
            {
                return methodInfo.IsDefined(typeof(UnitOfWorkAttribute), true);
            }

         

  • 相关阅读:
    idea actiBPM插件之中文乱码
    quartz 集成到Spring中
    Spring 中将service 注入到普通的工具类中
    idea 将java 项目 打包成jar包
    异常来自 HRESULT:0x80070057 (E_INVALIDARG))
    Entity Framework小知识
    C# Unix时间戳转换
    Asp.NET MVC+WebAPI跨域调用
    位运算逻辑与逻辑或逻辑非运算 c# 中如何使用
    c# 学习笔记 重载、重写、重构、构造函数、new、Class
  • 原文地址:https://www.cnblogs.com/cloudsu/p/11790635.html
Copyright © 2011-2022 走看看