zoukankan      html  css  js  c++  java
  • 一个分布式调用框架

    场景:

    一个服务端(S), n个客户端(C1,C2...Cn),   Cx1 通过 S 调用 Cx2  ,x1,x2属于{1,2,3...n},上指定的方法

    采用WCF,并且采用泛型 实现强类型编程

    过程,C1在S上发出消息(通过消息推送服务器),C2收到消息后,执行方法并上报进度与结果

     注意

        IIS中AppDomain是否是一个的

        C2上的消息处理不在UI线程,

    步骤1:

    定于输入输出类,声明接口并定于实现(调用模板方法)

    输入输出结构--注意命名空间跟类名要C与S端一致

        public class TestARequest
        {
    
            public long Id { get; set; }
    
            public String Name { get; set; }
    
            public List<String> Items { get; set; }
        }
    
        public class TestAResponse
        {
    
            public long Id { get; set; }
    
            public String Name { get; set; }
    
            public List<String> Items { get; set; }
        }
    View Code

    接口与实现

            public LongInvokeBucketInfo TestAStartInvoke(string position, string methodName, TestARequest request)
            {
                Action<LongInvokeBucket> nofityAct = (bucket) => 
                {
    
                    NotifyUtil.PostCSCNotify(bucket.Guid, position, methodName,null);
    
                };
    
                return LongInvokeBucketMgr.StartInvoke4CSC<TestARequest, TestAResponse>(nofityAct,request);
    
            }
    
            public LongInvokeResponse<TestAResponse> TestALoopInvoke(LongInvokeBucketInfo request)
            {
                return LongInvokeBucketMgr.LoopInvoke<TestAResponse>(request);
            }
    
            public String TestARefreshInvoke(LongInvokeResponse<TestAResponse> request)
            {
    
                return LongInvokeBucketMgr.RefreshInvoke(request);
            }
            public LongInvokeResponse<TestARequest> TestALoadInvokeParam(String guid)
            {
                return LongInvokeBucketMgr.LoadInvokeParam<TestARequest>(guid);
     
            }
    View Code

    客端户执行方法格式

            public void TestA(String guid)
            {
    
    
                var link = new LongInvokeLink<TestARequest, TestAResponse, IKX_InvokeService>();
                try
                {
    
                    var callParam= link.Begin(guid);
                    link.P(string.Format("收到Name:{0},Items.Count:{1}", callParam.Name, callParam.Items.Count),10);
                    Thread.Sleep(1000 * 2);
                    link.P("执行一些费劲的操作...");
                    Thread.Sleep(1000 * 3);
                    link.P(80);
                    link.P("要返回了...");
                    Thread.Sleep(1000 * 2);
                    #region 构建方法返回
                    var rModle = new TestAResponse() { Id = 2, Name = "张士大夫" };//执行结果
                    rModle.Items = new List<string>();
                    for (int i = 0; i < 100; i++)
                    {
                        rModle.Items.Add("第Item" + i);
                    }
                    #endregion
                    link.Complete4Success(rModle);
                }
                catch (Exception ex)
                {
                    link.Complete4Fail(ex.Message);
                }
            }
    View Code

    执行方法需要定义在反射能获取到的类型里

            const String C_KXKey = "-KXInvoke:";
            const String C_KXKey2 = "-KXInvoke2:";
            /// <summary>
            /// 对应SimpleMsgClientHandle
            /// 如果开头是$KXInvoke:
            /// 那么使用本扩展
            /// 格式 $KXInvoke:方法名,参数1,参数2...
            /// </summary>
            /// <param name="msg"></param>
            private bool MsgHandleExtension(string msg)
            {
              
                try
                {
                    var argTypes = new List<Type>();
                    var methodName = "";
                    var args = new List<Object>();
                    if (msg.StartsWith(C_KXKey))
                    {
                        #region 模式A
                        var arr = msg.Substring(C_KXKey.Length).Split("$".ToCharArray());
                        var invokeId = 0L;
                        if (arr.Length >= 2)
                        {
                            invokeId = long.Parse(arr[0]);
                            methodName = arr[1];
                            args.Add(invokeId);
                        }
                        argTypes.Add(typeof(long));
                        for (int i = 2; i < arr.Length; i++)
                        {
                            args.Add(arr[i]);
                            argTypes.Add(typeof(String));
                        }
                        #endregion
                    }
                    else if (msg.StartsWith(C_KXKey2))
                    {
                        #region 模式A
                        var arr = msg.Substring(C_KXKey2.Length).Split("$".ToCharArray());
                        var guid = "";
                        if (arr.Length >= 2)
                        {
                            guid = arr[0].Trim();
                            methodName = arr[1];
                            args.Add(guid);
                        }
                        argTypes.Add(typeof(String));
                        for (int i = 2; i < arr.Length; i++)
                        {
                            args.Add(arr[i]);
                            argTypes.Add(typeof(String));
                        }
                        #endregion
                    }
    
                    #region 执行反射调用
                    var method = this.GetType().GetMethod(methodName, argTypes.ToArray());
                    if (method != null)
                    {
                        if (args.Count <= 0)
                        {
                            method.Invoke(this, null); //单线程同步处理
                        }
                        else
                        {
                            method.Invoke(this, args.ToArray());
                        }
                    }
                    else
                    {
                        Console.WriteLine("没有Public签名的方法:" + methodName);
                    }
                    #endregion
    
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                return true;
            }
    View Code

    调用端:

                try
                {
                    var method = "TestA";// txtMethod.Text.Trim();
                    var argsStr = txtArgs.Text.Trim();
                    var position = cbxPosition.Text.Trim();
                    if (string.IsNullOrWhiteSpace(method) || string.IsNullOrWhiteSpace(position))
                    {
                        throw new Exception("必需提供方法名称与工位!");
                    }
                    var service =ServiceRTLocator.New<IKX_InvokeService>();
    
                    var request = new TestARequest() { Id = 999, Name = "9999",Items=new List<string>() };
                    request.Items.AddRange(new String[] {"A","B","C" });
    
    
    
                    var v = LongInvoke<TestARequest, TestAResponse>(request,position,method, new LongInvokeControl(service, "TestAStartInvoke", "TestALoopInvoke"));
                    this.kXInvokeBindingSource.DataSource = v.Items;
                }
                catch (Exception ex)
                {
                    ErrMsg(ex.Message);
                }
    View Code

    //===注意 2个反射代码-------其他的不再使用了,留备用

                    else if (msg.StartsWith(C_KXKey2))
                    {
                        #region 模式B
                        var arr = msg.Substring(C_KXKey2.Length).Split("$".ToCharArray());
                        var guid = "";
                        if (arr.Length >= 2)
                        {
                            guid = arr[0].Trim();
                            methodName = arr[1];
                            args.Add(guid);
                        }
                        argTypes.Add(typeof(String));
                        for (int i = 2; i < arr.Length; i++)
                        {
                            args.Add(arr[i]);
                            argTypes.Add(typeof(String));
                        }
                        #endregion
    
                        var invokeInfo = FetchInfo(methodName); //针对方法路由
                        var methodInfo = invokeInfo.Impl.GetType().GetMethod(methodName);
                        var ps = methodInfo.GetParameters();
                        var attrs = methodInfo.GetCustomAttributes(typeof(KXInvokeAttribute), false);
                        if (attrs.Length > 0)
                        {
                            CallContext.SetData(C_KXMethodName, methodName);
                            Object linkSvc = null;
                            MethodInfo loadParamMInfo = null;
                            MethodInfo failMInfo = null;
                            MethodInfo completedMInfo = null;
    
                            try
                            {
                                #region 采用无感模式
                                var attr = attrs[0] as KXInvokeAttribute;
                                //var serviceTypeName = attr.Action;
                                //var serviceType= FetchInfo(serviceTypeName).InterfaceType;
                                #region Action 中设置com.geelyhdIServer.IKX_InvokeSerive
                                //var segmentList = serviceTypeName.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                                ////类型不在同个程序集合
                                //var interfaceName= segmentList.LastOrDefault();
                                //var assembleName= serviceTypeName.Replace("." + interfaceName,"");
                                //var serviceType = Assembly.Load(assembleName).GetType(serviceTypeName);
                                #endregion
    
                                var inType = ps[0].ParameterType;
                                var outType = methodInfo.ReturnType;
                                var linkGenericType =typeof(LongInvokeLink<,,>);
                                //var linkGenericType = Type.GetType("XXXX....LongInvokeLink`3");
                                var linkType = linkGenericType.MakeGenericType(inType, outType, serviceType);
                                completedMInfo = linkType.GetMethod("Complete4Success");
                                failMInfo = linkType.GetMethod("Complete4Fail");
                                loadParamMInfo = linkType.GetMethod("Begin");
                                linkSvc = Activator.CreateInstance(linkType, guid);
                                //获取输入参数
                                var inModel = loadParamMInfo.Invoke(linkSvc, null);
    
                                CallContext.SetData(C_KXLink, linkSvc);
                                //执行调用
                                var outModel = methodInfo.Invoke(_MethodHost, new object[] { inModel });
                                //上传返回值
                                completedMInfo.Invoke(linkSvc, new object[] { outModel });
                               
                                #endregion
                            }
                            catch (Exception ex)
                            {
                                if (linkSvc != null && failMInfo!=null)
                                {
                                    failMInfo.Invoke(linkSvc, new Object[] { ex.Message });
                                }
                            }
                            finally
                            {
                                CallContext.SetData(C_KXMethodName, null);
                                CallContext.FreeNamedDataSlot(C_KXMethodName);
                                CallContext.SetData(C_KXLink, null);
                                CallContext.FreeNamedDataSlot(C_KXLink);
    
                            }
                            return true;
                        }
    View Code

    透明代理

    namespace F.Studio.KXInvoke
    {
        public class KXInvokeLocalHandle : MarshalByRefObject
        {
            /// <summary>
            /// 变成http方式传输
            /// Post方式
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            public KXInvokeEntity Do(KXInvokeEntity callEnt)
            {
    
                Console.WriteLine("方法执行了!");
                return callEnt;
            }
        }
    
        public class KXInvokeEntity
        {
            public String MethodName { get; set; }
            public String InterfaceName { get; set; }
            public Object InModel { get; set; }
            public Object OutModel { get; set; }
            public static KXInvokeEntity Parse(IMethodCallMessage msg)
            {
                var ent = new KXInvokeEntity();
    
                ent.MethodName = msg.MethodName;
                ent.InterfaceName = Type.GetType(msg.TypeName,true,true).FullName;
                ent.InModel = msg.InArgs[0];
                return ent;
    
            }
        }
    
        public class KXInvokeProxy : RealProxy
        {
            private KXInvokeLocalHandle _Handler;
    
            public KXInvokeProxy(Type type)
                : base(type)
            {
                _Handler = new KXInvokeLocalHandle();
            }
    
            public override IMessage Invoke(IMessage msg)
            {
                PreProceede(msg);
                IMethodCallMessage callMessage = (IMethodCallMessage)msg;
    
                var  callEnt = _Handler.Do(KXInvokeEntity.Parse( callMessage));
    
    
                PostProceede(msg);
                return new ReturnMessage(callEnt.OutModel, new object[0], 0, null, callMessage);
            }
            public void PreProceede(IMessage msg)
            {
                Console.WriteLine("方法执行前");
            }
            public void PostProceede(IMessage msg)
            {
                Console.WriteLine("方法执行后");
            }
        }
    
        public class KXInvokeFactory
        {
            public static T Fetch<T>()
                where T : class
            {
                var realProxy = new KXInvokeProxy(typeof(T));
                var transparentProxy = realProxy.GetTransparentProxy();
                return realProxy.GetTransparentProxy() as T;
            }
    
        }
    }
    View Code
  • 相关阅读:
    PostThreadMessage
    WaitForSingleObject函数的使用
    CodeWarrior环境下中断使用
    Activity跳转时生命周期跟踪
    win7 VS2012+openCV-2.4.11 配置
    CodeBlocks16.01+wxWidgets3.0.2
    MFC一个类访问另一个类成员对象的成员变量值
    无法打开包括文件:'atlrx.h'的解决办法
    STM32f103的数电采集电路的TIMER定时器的使用与时序控制的程序
    STM32f103的数电采集电路的双ADC的设计与使用
  • 原文地址:https://www.cnblogs.com/wdfrog/p/14646922.html
Copyright © 2011-2022 走看看