Exemplo n.º 1
0
        public void ScanAssemblies(Assembly[] asmList)
        {
            //扫描一下
            foreach (var asm in asmList)
            {
                foreach (var t in asm.GetTypes())
                {
                    if (RpcUtil.IsHeritedType(t, "Actor"))
                    {
                        RegisterType(t.Name, t);
                    }
                }
            }

            foreach (var asm in asmList)
            {
                foreach (var t in asm.GetTypes())
                {
                    var refTypeAttrs = t.GetCustomAttributes(typeof(RefTypeAttribute));
                    if (refTypeAttrs.Count() > 0)
                    {
                        var rta = (RefTypeAttribute)refTypeAttrs.First();
                        //var rtaType = Global.TypeManager.Get(rta.TypeName);
                        Global.TypeManager.RegisterRefType(t, rta.TypeName);
                    }

                    var msgTypeAttrs = t.GetCustomAttributes(typeof(MessageTypeAttribute));
                    if (msgTypeAttrs.Count() > 0)
                    {
                        var mta = (MessageTypeAttribute)msgTypeAttrs.First();
                        Global.TypeManager.RegisterMessageType(mta.ProtoCode, t);
                    }
                }
            }
        }
Exemplo n.º 2
0
        public static void AutogenActor(Assembly asm, bool isServer, string sharedPath, string clientPath, string serverPath)
        {
            List <Type> actorTypes = new List <Type>();

            foreach (Type type in asm.GetTypes())
            {
                if (type.IsAbstract)
                {
                    continue;
                }

                if (!RpcUtil.IsHeritedType(type, "Actor"))
                {
                    continue;
                }

                var attr = GetAttribute <ActorTypeAttribute>(type);
                if (attr == null)
                {
                    continue;
                }

                var at = (int)attr.AType;
                if (isServer && at != (int)AType.SERVER)
                {
                    continue;
                }
                if (!isServer && at != (int)AType.CLIENT)
                {
                    continue;
                }

                actorTypes.Add(type);
            }

            GenProtoCode(actorTypes, sharedPath, clientPath, serverPath);

            foreach (var type in actorTypes)
            {
                GenFromActorType(type, sharedPath, clientPath, serverPath);
            }
        }
Exemplo n.º 3
0
        static void GenFromActorType(Type type, string sharedPath, string clientPath, string serverPath)
        {
            var rpcDefineDic       = new SortedDictionary <string, string>();
            var apiDefineDic       = new SortedDictionary <string, string>();
            var apiNativeDefineDic = new SortedDictionary <string, string>();

            if (GetAttribute <ActorTypeAttribute>(type) == null && type.Name != "Host")
            {
                return;
            }

            bool isServer = type.Name == "Host" ? true : ((int)GetAttribute <ActorTypeAttribute>(type).AType == (int)AType.SERVER);

            var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            for (int i = 0; i < methods.Length; ++i)
            {
                MethodInfo method = methods[i];
                var        attr   = GetAttribute <ServerApiAttribute>(method);
                Api        api    = Api.NoneApi;
                if (attr != null)
                {
                    api = Api.ServerApi;
                }
                else
                {
                    attr = GetAttribute <ServerOnlyAttribute>(method);
                    if (attr != null)
                    {
                        api = Api.ServerOnly;
                    }
                    else
                    {
                        attr = GetAttribute <ClientApiAttribute>(method);
                        if (attr != null)
                        {
                            api = Api.ClientApi;
                        }
                    }
                }

                if (api == Api.ClientApi)
                {
                    if (RpcUtil.IsHeritedType(type, "Service"))
                    {
                        Log.Info(string.Format("client_api not allowed in Service {0}", type.Name));
                        continue;
                    }
                }

                if (api != Api.NoneApi)
                {
                    var methodParameterList = method.GetParameters();

                    if (type.Name == "Host")
                    {
                        methodParameterList = methodParameterList.Slice(0, methodParameterList.Length - 1);
                    }

                    uint code = Basic.GenID32FromName(method.Name);

                    //现在生成message
                    string message_type = method.Name + GetApiMessagePostfix(api);

                    string message_fields = ParseMessageFields(methodParameterList, "        ");

                    string callback_define = GenCallbackMsgDecl(methodParameterList,
                                                                GetCallbackArgs(method),
                                                                "        ");

                    string itype = "IMessage";
                    if (callback_define != "")
                    {
                        itype = "IMessageWithCallback";
                    }

                    string proto_code = NameToProtoCode(method.Name) + "_" + GetApiMessagePostfix(api).ToUpper();

                    string msg_ns = type.Name == "Host" ? "Fenix.Common.Message" : "Shared.Message";

                    string pc_cls = type.Name == "Host" ? "OpCode" : "ProtocolCode";

                    var msgBuilder = new StringBuilder()
                                     .AppendLine($"//AUTOGEN, do not modify it!\n")
                                     .AppendLine($"using Fenix.Common;")
                                     .AppendLine($"using Fenix.Common.Attributes;")
                                     .AppendLine($"using Fenix.Common.Rpc;")
                                     .AppendLine($"using MessagePack; ")
                                     .AppendLine($"using System.ComponentModel;");

                    if (type.Name != "Host")
                    {
                        msgBuilder.AppendLine($"using Shared;")
                        .AppendLine($"using Shared.Protocol;")
                        .AppendLine($"using Shared.DataModel;");
                    }
                    msgBuilder.AppendLine($"using System; ")
                    .AppendLine($"")
                    .AppendLine($"namespace {msg_ns}")
                    .AppendLine($"{{")
                    .AppendLine($"    [MessageType({pc_cls}.{proto_code})]")
                    .AppendLine($"    [MessagePackObject]")
                    .AppendLine($"    public class {message_type} : {itype}")
                    .AppendLine($"    {{")
                    .AppendLine($"{message_fields}");

                    if (callback_define != "")
                    {
                        msgBuilder.AppendLine(@"
        [Key(199)]
        public Callback callback
        {
            get => _callback as Callback;
            set => _callback = value;
        } 
").AppendLine($"{callback_define}");
                    }

                    msgBuilder.AppendLine($"    }}")
                    .AppendLine($"}}");

                    var msgCode = msgBuilder.ToString();

                    using (var sw = new StreamWriter(Path.Combine(sharedPath, "Message", message_type + ".cs"), false, Encoding.UTF8))
                    {
                        sw.WriteLine(msgCode.Replace("\r", ""));
                    }

                    //现在生成actor_ref定义
                    var rpc_name = "rpc_" + NameToApi(method.Name);
                    if (api == Api.ClientApi)
                    {
                        rpc_name = "client_on_" + NameToApi(method.Name);
                    }
                    else if (api == Api.ServerOnly)
                    {
                        rpc_name = "rpc_" + NameToApi(method.Name);
                    }

                    if (type.Name == "Host")
                    {
                        rpc_name = method.Name;
                    }

                    string args_decl = ParseArgsDecl(methodParameterList);

                    string typename = type.Name;
                    string args     = ParseArgs(methodParameterList);

                    string method_name = method.Name;
                    //string msg_type = method.Name + GetApiMessagePostfix(api);
                    string msg_assign = ParseArgsMsgAssign(methodParameterList, "                ");

                    StringBuilder builder;

                    if (callback_define != "")
                    {
                        var    cbType  = methodParameterList.Where(m => m.Name == "callback").First().ParameterType;
                        string cb_args = GenCbArgs(cbType.GetGenericArguments(), GetCallbackArgs(method), "cbMsg.");

                        builder = new StringBuilder()
                                  .AppendLine($"        public void {rpc_name}({args_decl})")
                                  .AppendLine($"        {{")
                                  .AppendLine($"            var toHostId = Global.IdManager.GetHostIdByActorId(this.toActorId, this.isClient);")
                                  .AppendLine($"            if (this.FromHostId == toHostId)")
                                  .AppendLine($"            {{")
                                  .AppendLine($"                var protoCode = {pc_cls}.{proto_code};")
                                  .AppendLine($"                if (protoCode < OpCode.CALL_ACTOR_METHOD)")
                                  .AppendLine($"                {{")
                                  .AppendLine($"                    var peer = NetManager.Instance.GetPeerById(this.FromHostId, this.NetType);")
                                  .AppendLine($"                    var context = new RpcContext(null, peer);");
                        if (args.Trim().Length == 0)
                        {
                            builder.AppendLine($"                    Global.Host.CallMethodWithParams(protoCode, new object[] {{ context }});");
                        }
                        else
                        {
                            builder.AppendLine($"                    Global.Host.CallMethodWithParams(protoCode, new object[] {{ {args}, context }});");
                        }
                        builder.AppendLine($"                }}")
                        .AppendLine($"                else")
                        .AppendLine($"                    Global.Host.GetActor(this.toActorId).CallMethodWithParams(protoCode, new object[] {{ {args} }});")
                        //.AppendLine($"                Global.Host.GetActor(this.toActorId).CallLocalMethod({pc_cls}.{proto_code}, new object[] {{ {args} }});")
                        //.AppendLine($"                (({typename})Global.Host.GetActor(this.toActorId)).{method_name}({args});")
                        .AppendLine($"                return;")
                        .AppendLine($"            }}")
                        .AppendLine($"            var msg = new {message_type}()")
                        .AppendLine($"            {{")
                        .AppendLine($"{msg_assign}")
                        .AppendLine($"            }};")
                        .AppendLine($"            var cb = new Action<byte[]>((cbData) => {{")
                        .AppendLine($"                var cbMsg = cbData==null?new {message_type}.Callback():RpcUtil.Deserialize<{message_type}.Callback>(cbData);")
                        .AppendLine($"                callback?.Invoke({cb_args});")
                        .AppendLine($"            }});")
                        .AppendLine($"            this.CallRemoteMethod({pc_cls}.{proto_code}, msg, cb);")
                        .AppendLine($"        }}");
                    }
                    else
                    {
                        builder = new StringBuilder()
                                  .AppendLine($"        public void {rpc_name}({args_decl})")
                                  .AppendLine($"        {{")
                                  .AppendLine($"           var toHostId = Global.IdManager.GetHostIdByActorId(this.toActorId, this.isClient);")
                                  .AppendLine($"           if (this.FromHostId == toHostId)")
                                  .AppendLine($"           {{")
                                  .AppendLine($"                var protoCode = {pc_cls}.{proto_code};")
                                  .AppendLine($"                if (protoCode < OpCode.CALL_ACTOR_METHOD)")
                                  .AppendLine($"                {{")
                                  .AppendLine($"                    var peer = NetManager.Instance.GetPeerById(this.FromHostId, this.NetType);")
                                  .AppendLine($"                    var context = new RpcContext(null, peer);");
                        if (args.Trim().Length == 0)
                        {
                            builder.AppendLine($"                    Global.Host.CallMethodWithParams(protoCode, new object[] {{ context }});");
                        }
                        else
                        {
                            builder.AppendLine($"                    Global.Host.CallMethodWithParams(protoCode, new object[] {{ {args}, context }});");
                        }
                        builder.AppendLine($"                }}")
                        .AppendLine($"                else")
                        .AppendLine($"                    Global.Host.GetActor(this.toActorId).CallMethodWithParams(protoCode, new object[] {{ {args} }}); ")
                        //.AppendLine($"                Global.Host.GetActor(this.toActorId).CallLocalMethod({pc_cls}.{proto_code}, new object[] {{ {args} }});")
                        //.AppendLine($"                (({typename})Global.Host.GetActor(this.toActorId)).{method_name}({args});")
                        .AppendLine($"               return;")
                        .AppendLine($"           }}")
                        .AppendLine($"           var msg = new {message_type}()")
                        .AppendLine($"           {{")
                        .AppendLine($"{msg_assign}")
                        .AppendLine($"           }};")
                        .AppendLine($"           this.CallRemoteMethod({pc_cls}.{proto_code}, msg, null);")
                        .AppendLine($"        }}");
                    }

                    var rpcDefineCode = builder.ToString();
                    rpcDefineDic[rpc_name] = rpcDefineCode;


                    string api_rpc_args = ParseArgs(methodParameterList, "_msg.", "callback");
                    string api_type     = "ServerApi";
                    string api_name     = "SERVER_API_" + NameToApi(method.Name);
                    if (api == Api.ClientApi)
                    {
                        api_name = "CLIENT_API_" + NameToApi(method.Name);
                        api_type = "ClientApi";
                    }
                    else if (api == Api.ServerOnly)
                    {
                        api_name = "SERVER_ONLY_" + NameToApi(method.Name);
                        api_type = "ServerOnly";
                    }
                    builder = new StringBuilder()
                              .AppendLine($"        [RpcMethod({pc_cls}.{proto_code}, Api.{api_type})]")
                              .AppendLine($"        [EditorBrowsable(EditorBrowsableState.Never)]");
                    if (type.Name == "Host")
                    {
                        if (callback_define != "")
                        {
                            builder.AppendLine($"        public void {api_name}(IMessage msg, Action<object> cb, RpcContext context)");
                        }
                        else
                        {
                            builder.AppendLine($"        public void {api_name}(IMessage msg, RpcContext context)");
                        }
                    }
                    else
                    {
                        if (callback_define != "")
                        {
                            builder.AppendLine($"        public void {api_name}(IMessage msg, Action<object> cb)");
                        }
                        else
                        {
                            builder.AppendLine($"        public void {api_name}(IMessage msg)");
                        }
                    }


                    builder.AppendLine($"        {{")
                    .AppendLine($"            var _msg = ({message_type})msg;");


                    if (callback_define != "")
                    {
                        var    cbType2       = methodParameterList.Where(m => m.Name == "callback").First().ParameterType;
                        string api_cb_args   = GenCbArgs(cbType2.GetGenericArguments(), GetCallbackArgs(method), "");
                        string api_cb_assign = ParseArgsMsgAssign(cbType2.GetGenericArguments(),
                                                                  GetCallbackArgs(method),
                                                                  "                ",
                                                                  "cbMsg.");
                        builder.AppendLine($"            this.{method.Name}({api_rpc_args}, ({api_cb_args}) =>")
                        .AppendLine($"            {{")
                        .AppendLine($"                var cbMsg = new {message_type}.Callback();")
                        .AppendLine($"{api_cb_assign}")
                        .AppendLine($"                cb.Invoke(cbMsg);");
                        if (type.Name == "Host")
                        {
                            builder.AppendLine($"            }}, context);");
                        }
                        else
                        {
                            builder.AppendLine($"            }});");
                        }
                    }
                    else
                    {
                        if (type.Name == "Host")
                        {
                            builder.AppendLine($"            this.{method.Name}({api_rpc_args}, context);");
                        }
                        else
                        {
                            builder.AppendLine($"            this.{method.Name}({api_rpc_args});");
                        }
                    }

                    builder.AppendLine($"        }}");

                    var apiDefineCode = builder.ToString();
                    apiDefineDic[api_name] = apiDefineCode;

                    api_type = "ServerApi";
                    api_name = "SERVER_API_NATIVE_" + NameToApi(method.Name);
                    if (api == Api.ClientApi)
                    {
                        api_name = "CLIENT_API_NATIVE_" + NameToApi(method.Name);
                        api_type = "ClientApi";
                    }
                    else if (api == Api.ServerOnly)
                    {
                        api_name = "SERVER_ONLY_NATIVE_" + NameToApi(method.Name);
                        api_type = "ServerOnly";
                    }

                    builder = new StringBuilder()
                              .AppendLine($"        [RpcMethod({pc_cls}.{proto_code}, Api.{api_type})]")
                              .AppendLine($"        [EditorBrowsable(EditorBrowsableState.Never)]");
                    if (type.Name == "Host")
                    {
                        if (callback_define != "")
                        {
                            builder.AppendLine($"        public void {api_name}({args_decl}, RpcContext context)");
                        }
                        else
                        {
                            builder.AppendLine($"        public void {api_name}({args_decl}, RpcContext context)");
                        }
                    }
                    else
                    {
                        if (callback_define != "")
                        {
                            builder.AppendLine($"        public void {api_name}({args_decl})");
                        }
                        else
                        {
                            builder.AppendLine($"        public void {api_name}({args_decl})");
                        }
                    }

                    if (callback_define != "")
                    {
                        var cbType2 = methodParameterList.Where(m => m.Name == "callback").First().ParameterType;
                        //string api_cb_args = GenCbArgs(cbType2.GetGenericArguments(), GetCallbackArgs(method), "");
                        if (type.Name == "Host")
                        {
                            builder.AppendLine($"        {{\n            this.{method.Name}({args}, context);");
                        }
                        else
                        {
                            builder.AppendLine($"        {{\n            this.{method.Name}({args});");
                        }
                    }
                    else
                    {
                        if (type.Name == "Host")
                        {
                            builder.AppendLine($"        {{\n            this.{method.Name}({args}, context);");
                        }
                        else
                        {
                            builder.AppendLine($"        {{\n            this.{method.Name}({args});");
                        }
                    }

                    builder.AppendLine($"        }}");

                    var apiNativeDefineCode = builder.ToString();
                    apiNativeDefineDic[api_name] = apiNativeDefineCode;
                }
            }

            string refCode = string.Join("\n", rpcDefineDic.Values);
            string tname   = type.Name;
            string ns      = type.Namespace;

            var alAttr = GetAttribute <AccessLevelAttribute>(type);

            if (alAttr == null && type.Name != "Host")
            {
                Log.Info(string.Format("ERROR: {0} has no AccessLevel", type.Name));
                return;
            }

            if (type.Name != "Host")
            {
                var al = alAttr.AccessLevel;
                Log.Info(string.Format("AccessLevel {0} : {1}", type.Name, al));
            }

            string root_ns = type.Name == "Host" ? "Fenix":(isServer ? "Server" : "Client");

            string refTypeName = tname == "Avatar" ? type.FullName : tname;

            var refBuilder = new StringBuilder()
                             .AppendLine(@"
//AUTOGEN, do not modify it!

using Fenix;
using Fenix.Common;
using Fenix.Common.Attributes;
using Fenix.Common.Utils;
using Fenix.Common.Message;

using Shared;
using Shared.DataModel;
using Shared.Protocol; 
using Shared.Message;
")
                             .AppendLine(@"using MessagePack; 
using System;
")
                             .AppendLine($"namespace {root_ns}")
                             .AppendLine(@"{
");

            if (type.Name != "Host")
            {
                refBuilder.AppendLine($"    [RefType(\"{refTypeName}\")]")
                .AppendLine($"    public partial class {tname}Ref : ActorRef");
            }
            else
            {
                refBuilder.AppendLine($"    public partial class ActorRef");
            }
            refBuilder.AppendLine($"    {{")
            .AppendLine($"{refCode}    }}")
            .AppendLine($"}}");
            var result = refBuilder.ToString();

            if (type.Name == "Host")
            {
                using (var sw = new StreamWriter(Path.Combine(sharedPath, "../Actor", "ActorRef.rpc.cs"), false, Encoding.UTF8))
                {
                    sw.WriteLine(result);
                }
            }
            else
            {
                using (var sw = new StreamWriter(Path.Combine(sharedPath, "ActorRef", root_ns, type.Name + "Ref.cs"), false, Encoding.UTF8))
                {
                    sw.WriteLine(result);
                }
            }


            string internalApiCode       = string.Join("\n", apiDefineDic.Values);
            string internalNativeApiCode = string.Join("\n", apiNativeDefineDic.Values);

            var apiBuilder = new StringBuilder()
                             .AppendLine(@"
//AUTOGEN, do not modify it!

using Fenix.Common;
using Fenix.Common.Attributes;
using Fenix.Common.Message;
using Fenix.Common.Rpc;
using Fenix.Common.Utils;
using Shared;
using Shared.DataModel;
using Shared.Protocol; 
using Shared.Message;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

")
                             .AppendLine($"namespace {ns}")
                             .AppendLine("{")
                             .AppendLine($"    public partial class {tname}")
                             .AppendLine($"    {{")
                             .AppendLine($"{internalApiCode}")
                             .AppendLine($"{internalNativeApiCode}   }}")
                             .AppendLine($"}}");


            var apiResultCode = apiBuilder.ToString();

            //if (type.Name != "Host")
            //{
            string output = isServer ? serverPath : clientPath;

            using (var sw = new StreamWriter(Path.Combine(output, "Stub", type.Name + ".Stub.cs"), false, Encoding.UTF8))
            {
                sw.WriteLine(apiResultCode);
            }
            //}
            //else
            //{
            //    using (var sw = new StreamWriter(Path.Combine(serverPath, "Stub", type.Name + ".Stub.cs"), false, Encoding.UTF8))
            //    {
            //        sw.WriteLine(apiResultCode);
            //    }

            //    using (var sw = new StreamWriter(Path.Combine(clientPath, "Stub", type.Name + ".Stub.cs"), false, Encoding.UTF8))
            //    {
            //        sw.WriteLine(apiResultCode);
            //    }
            //}
        }