首页 > 其他 > 详细

WCF 动态代理与拦截器

时间:2020-12-18 14:44:30      阅读:26      评论:0      收藏:0      [点我收藏+]

使用Castle.Core.dll实现,核心代码是使用Castle.DynamicProxy.ProxyGenerator类的CreateInterfaceProxyWithoutTarget方法动态创建代理对象

1.WCF服务端通过动态代理,在拦截器中校验Ticket、处理异常

服务端动态代理工厂类ProxyFactory代码:

技术分享图片
using Castle.DynamicProxy;
using SunCreate.Common.Base;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace SunCreate.InfoPlatform.Server.Service
{
    /// <summary>
    /// 动态代理工厂
    /// </summary>
    public class ProxyFactory
    {
        /// <summary>
        /// 拦截器缓存
        /// </summary>
        private static ConcurrentDictionary<Type, IInterceptor> _interceptors = new ConcurrentDictionary<Type, IInterceptor>();

        /// <summary>
        /// 代理对象缓存
        /// </summary>
        private static ConcurrentDictionary<Type, object> _objs = new ConcurrentDictionary<Type, object>();

        /// <summary>
        /// 动态创建代理
        /// </summary>
        /// <typeparam name="T">接口</typeparam>
        public static T CreateProxy<T>()
        {
            Type interfaceType = typeof(T);

            string serviceName = interfaceType.Name.Substring(1); //服务名称
            T _impl = HI.Get<T>();
            IInterceptor interceptor = _interceptors.GetOrAdd(interfaceType, type => new ProxyInterceptor<T>(_impl));

            ProxyGenerator proxyGenerator = new ProxyGenerator();
            return (T)_objs.GetOrAdd(interfaceType, type => proxyGenerator.CreateInterfaceProxyWithoutTarget(typeof(T), interceptor)); //根据接口类型动态创建代理对象,接口没有实现类
        }
    }
}
View Code

服务端拦截器类ProxyInterceptor<T>代码:

技术分享图片
using Castle.DynamicProxy;
using log4net;
using SunCreate.Common.Base;
using SunCreate.InfoPlatform.Server.Bussiness;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;

namespace SunCreate.InfoPlatform.Server.Service
{
    /// <summary>
    /// 拦截器
    /// </summary>
    /// <typeparam name="T">接口</typeparam>
    public class ProxyInterceptor<T> : IInterceptor
    {
        private static ILog _log = LogManager.GetLogger(typeof(ProxyInterceptor<T>));

        private T _impl;

        public ProxyInterceptor(T impl)
        {
            _impl = impl;
        }

        /// <summary>
        /// 拦截方法
        /// </summary>
        public void Intercept(IInvocation invocation)
        {
            //准备参数
            ParameterInfo[] parameterInfoArr = invocation.Method.GetParameters();
            object[] valArr = new object[parameterInfoArr.Length];
            for (int i = 0; i < parameterInfoArr.Length; i++)
            {
                valArr[i] = invocation.GetArgumentValue(i);
            }

            //执行方法
            try
            {
                if (HI.Get<ISecurityImp>().CheckTicket())
                {
                    invocation.ReturnValue = invocation.Method.Invoke(_impl, valArr);
                }
            }
            catch (Exception ex)
            {
                _log.Error("ProxyInterceptor " + typeof(T).Name + " " + invocation.Method.Name + " 异常", ex);
            }

            //out和ref参数处理
            for (int i = 0; i < parameterInfoArr.Length; i++)
            {
                ParameterInfo paramInfo = parameterInfoArr[i];
                if (paramInfo.IsOut || paramInfo.ParameterType.IsByRef)
                {
                    invocation.SetArgumentValue(i, valArr[i]);
                }
            }
        }
    }
}
View Code

如何使用:

技术分享图片
public List<EscortTask> GetEscortTaskList()
{
    var impl = ProxyFactory.CreateProxy<SunCreate.InfoPlatform.Server.Bussiness.IBussDataImp>();
    return impl.GetEscortTaskList();
}
View Code

这里不用再写try catch

2.WCF客户端通过动态代理,在拦截器中添加Ticket、处理异常、Close对象

客户端动态代理工厂类ProxyFactory代码:

技术分享图片
using Castle.DynamicProxy;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace SunCreate.InfoPlatform.Client.Bussiness.Imp
{
    /// <summary>
    /// 动态代理工厂
    /// </summary>
    public class ProxyFactory
    {
        /// <summary>
        /// 拦截器缓存
        /// </summary>
        private static ConcurrentDictionary<Type, IInterceptor> _interceptors = new ConcurrentDictionary<Type, IInterceptor>();

        /// <summary>
        /// 代理对象缓存
        /// </summary>
        private static ConcurrentDictionary<Type, object> _objs = new ConcurrentDictionary<Type, object>();

        /// <summary>
        /// 动态创建代理
        /// </summary>
        /// <typeparam name="T">接口</typeparam>
        public static T CreateProxy<T>()
        {
            Type interfaceType = typeof(T);

            string serviceName = interfaceType.Name.Substring(1); //服务名称
            ChannelFactory<T> channelFactory = new ChannelFactory<T>(serviceName);
            IInterceptor interceptor = _interceptors.GetOrAdd(interfaceType, type => new ProxyInterceptor<T>(channelFactory));

            ProxyGenerator proxyGenerator = new ProxyGenerator();
            return (T)_objs.GetOrAdd(interfaceType, type => proxyGenerator.CreateInterfaceProxyWithoutTarget(typeof(T), interceptor)); //根据接口类型动态创建代理对象,接口没有实现类
        }
    }
}
View Code

客户端拦截器类ProxyInterceptor<T>代码:

技术分享图片
using Castle.DynamicProxy;
using log4net;
using SunCreate.Common.Base;
using SunCreate.InfoPlatform.Client.Bussiness;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading.Tasks;

namespace SunCreate.InfoPlatform.Client.Bussiness.Imp
{
    /// <summary>
    /// 拦截器
    /// </summary>
    /// <typeparam name="T">接口</typeparam>
    public class ProxyInterceptor<T> : IInterceptor
    {
        private static ILog _log = LogManager.GetLogger(typeof(ProxyInterceptor<T>));

        private ChannelFactory<T> _channelFactory;

        public ProxyInterceptor(ChannelFactory<T> channelFactory)
        {
            _channelFactory = channelFactory;
        }

        /// <summary>
        /// 拦截方法
        /// </summary>
        public void Intercept(IInvocation invocation)
        {
            //准备参数
            ParameterInfo[] parameterInfoArr = invocation.Method.GetParameters();
            object[] valArr = new object[parameterInfoArr.Length];
            for (int i = 0; i < parameterInfoArr.Length; i++)
            {
                valArr[i] = invocation.GetArgumentValue(i);
            }

            //执行方法
            T server = _channelFactory.CreateChannel();
            using (OperationContextScope scope = new OperationContextScope(server as IContextChannel))
            {
                try
                {
                    HI.Get<ISecurityBussiness>().AddTicket();

                    invocation.ReturnValue = invocation.Method.Invoke(server, valArr);

                    var value = HI.Get<ISecurityBussiness>().GetValue();
                    ((IChannel)server).Close();
                }
                catch (Exception ex)
                {
                    _log.Error("ProxyInterceptor " + typeof(T).Name + " " + invocation.Method.Name + " 异常", ex);
                    ((IChannel)server).Abort();
                }
            }

            //out和ref参数处理
            for (int i = 0; i < parameterInfoArr.Length; i++)
            {
                ParameterInfo paramInfo = parameterInfoArr[i];
                if (paramInfo.IsOut || paramInfo.ParameterType.IsByRef)
                {
                    invocation.SetArgumentValue(i, valArr[i]);
                }
            }
        }
    }
}
View Code

如何使用:

技术分享图片
public List<EscortTask> GetEscortTaskList()
{
    var service = ProxyFactory.CreateProxy<SunCreate.InfoPlatform.Contract.IBussDataService>();
    return service.GetEscortTaskList();
}
View Code

这里不用再写try catch

 

WCF 动态代理与拦截器

原文:https://www.cnblogs.com/s0611163/p/14154429.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!