예제 #1
0
        public MessageContainer?Decode()
        {
            lock (this.lockToken) {
                if (this.currentBufferLength == 0)
                {
                    return(null);
                }

                int delimiterIndex = CoderHelper.CheckForDelimiter(this.currentBuffer, this.currentBufferLength);
                if (delimiterIndex != -1)
                {
                    if (this.IsValidChecksum(delimiterIndex))
                    {
                        var container = new MessageContainer(this.currentBuffer, delimiterIndex - 1);
                        this.currentBufferLength = CoderHelper.SliceBuffer(delimiterIndex, this.currentBuffer, this.currentBufferLength);
                        return(container);
                    }
                    else
                    {
                        this.currentBufferLength = CoderHelper.SliceBuffer(delimiterIndex, this.currentBuffer, this.currentBufferLength);
                        if (Logger.IsLoggingEnabled)
                        {
                            Logger.Log($"Discarded currupted message!");
                        }
                    }
                }
                return(null);
            }
        }
예제 #2
0
        private bool IsValidChecksum(int messageEndIndex)
        {
            var  checksum        = CoderHelper.CalculateChecksum(this.currentBuffer, 0, messageEndIndex - 1);
            byte messageChecksum = this.currentBuffer[messageEndIndex - 1];

            return(checksum == messageChecksum);
        }
예제 #3
0
        public void EncodeTestMethod()
        {
            string urlParams = "---1234567890---";
            string encoded   = CoderHelper.Encode(urlParams);

            Assert.IsTrue(encoded.StartsWith("_"));
        }
        private void Form_Send(object sender, SendEventArgs e)
        {
            Debug.WriteLine("");
            Debug.WriteLine("---------------------DEBUG STRINGS-----------------------");
            Debug.WriteLine("");
            Debug.WriteLine($"Code:{Environment.NewLine}{e.Code}");
            Debug.WriteLine($"Tokens:{Environment.NewLine}{e.ToString()}");


            //Init a copy of controlpoints
            Encoder ENCODER = new Encoder();

            ENCODER.SetControlPoints(SelectedPrg);
            //ENCODE THE PROGRAM
            byte[] ByteEncoded = ENCODER.EncodeBytes(e.Tokens);
            var    PSize       = BitConverter.ToInt16(ByteEncoded, 0);

            CoderHelper.ConsolePrintBytes(ByteEncoded, "Encoded");
            MessageBox.Show($"Resource compiled succceded{System.Environment.NewLine}Total size 2000 bytes{System.Environment.NewLine}Already used {PSize} bytes.", "T3000");

            // MessageBox.Show(Encoding.UTF8.GetString(ByteEncoded), "Tokens");
            SelectedPrg.ProgramCodes[Index_EditProgramCode].Code = ByteEncoded;
            //The need of this code, means that constructor must accept byte array and fill with nulls to needSize value
            SelectedPrg.ProgramCodes[Index_EditProgramCode].Count = 2000;
            SelectedPrg.Programs[Index_EditProgramCode].Length    = PSize;
            //Also that save, must recalculate and save the lenght in bytes of every programcode into program.lenght
            //Prg.Save($"{PrgPath.Substring(0,PrgPath.Length-4)}.PRG");
        }
예제 #5
0
        public void DecodeTest()
        {
            string encodedStr = "_3HGHNLNLS0tMTIzNDU2Nzg5MC0tLQ=="; // "_4736YWN0aW9uPWxvZ2luJmxvZ2luPTEyMyZwYXNzd2Q9MzIx";
            string decoded    = CoderHelper.Decode(encodedStr);

            Assert.AreEqual("---1234567890---", decoded);
        }
예제 #6
0
        public void DecodeTest2()
        {
            string encoded = "_17ZYWN0aW9uPXBpbmcmY2xpZW50PTEuMC40LjU=";
            string decoded = CoderHelper.Decode(encoded);

            Assert.IsTrue(decoded.Length > 0);
            Assert.IsTrue(decoded.Contains("ping"));
        }
예제 #7
0
        public void TestMessageChecksum()
        {
            byte[] bytes = new byte[] {
                4, 6, 4, 6, 6, 46, 6, 34, 64, 2, 64, 62, 47, 27, 247,
                4, 6, 4, 6, 6, 46, 6, 34, 64, 2, 64, 62, 47, 27, 247
            };

            byte[] bigBytes = new byte[8 * 1024];
            Array.Copy(bytes, bigBytes, bytes.Length);

            var calculatedChecksum = CoderHelper.CalculateChecksum(bytes, 0, bytes.Length);

            var newLength = CoderHelper.AddChecksum(bigBytes, 0, bytes.Length) + bytes.Length;

            byte checksumInBigBytes = bigBytes[bytes.Length];

            Assert.AreEqual(checksumInBigBytes, calculatedChecksum);

            var writer = new MessageStreamWriter();
            var reader = new MessageStreamReader();

            var loginRequest = new LoginRequest()
            {
                accessToken = "alsdjflakjsdf", username = "******"
            };
            var matchRequest = new MatchRequest()
            {
                value1 = 1, value2 = 2, value3 = 3, value4 = 4
            };

            writer.Write(loginRequest);
            writer.Write(matchRequest);
            writer.Use((buffer, len) => {
                reader.Add(buffer, len);
                var message = reader.Decode();
                Assert.IsTrue(message.Value.Is(200));
                Assert.AreEqual(loginRequest, message.Value.Parse <LoginRequest>());
                message = reader.Decode();
                Assert.IsTrue(message.Value.Is(201));
                Assert.AreEqual(matchRequest, message.Value.Parse <MatchRequest>());
                writer.DidWrite(len);
            });

            writer.Write(loginRequest);
            writer.Write(matchRequest);
            writer.currentBuffer[0] = 23;
            writer.Use((buffer, len) => {
                reader.Add(buffer, len);
                var message = reader.Decode();
                Assert.IsFalse(message.HasValue);
                Assert.IsTrue(message == null);
                message = reader.Decode();
                Assert.IsTrue(message.Value.Is(201));
                Assert.AreEqual(matchRequest, message.Value.Parse <MatchRequest>());
                writer.DidWrite(len);
            });
        }
 public void Write <TMessage>(TMessage message) where TMessage : ITypedMessage
 {
     lock (this.lockToken) {
         var startIndex = this.currentBufferLength;
         this.currentBufferLength += CoderHelper.WriteInt(message.type, this.currentBuffer, this.currentBufferLength);
         this.currentBufferLength += BinaryEncoder.Encode(message, this.currentBuffer, this.currentBufferLength);
         this.currentBufferLength += CoderHelper.AddChecksum(this.currentBuffer, startIndex, this.currentBufferLength);
         this.currentBufferLength += CoderHelper.InsertDelimiter(this.currentBuffer, this.currentBufferLength);
     }
 }
예제 #9
0
        public MessageContainer(byte[] buffer, int length)
        {
            this._buffer = bufferPool.Rent();
            CoderHelper.PackageBytes(length, buffer, this._buffer);
            this._length = length;

            var converter = _intConverterPool.Rent();
            var array     = converter.array;

            Array.Copy(buffer, array, sizeof(int));
            converter.array = array;
            this.type       = converter.value;
            _intConverterPool.Pay(converter);
        }
        private void EditCodeColumn(object sender, EventArgs e)
        {
            try
            {
                var row = view.CurrentRow;
                Index_EditProgramCode = row.GetValue <int>(NumberColumn) - 1;

                var form = new ProgramEditorForm();
                form.Caption = $"Edit Code: Panel 1 - Program {Index_EditProgramCode } - Label {SelectedPrg.Programs[Index_EditProgramCode].Description}";

                Debug.WriteLine("--------------ORIGINAL CODE-------------------");
                CoderHelper.ConsolePrintBytes(Codes[Index_EditProgramCode].Code, "Original");

                Decoder DECODER = new Decoder();

                DECODER.SetControlPoints(SelectedPrg);
                string ProgramText = DECODER.DecodeBytes(Codes[Index_EditProgramCode].Code);

                Debug.WriteLine("--------------NEW PROGRAM TEXT-------------------");
                Debug.WriteLine(ProgramText);

                //STEP 1: create a local copy of all identifiers
                form.Identifiers = DECODER.Identifiers;

                //STEP 2: Create a local copy for Control Basic program text
                form.SetCode(ProgramText);

                //STEP 3: Override Send Event Handler and encode program into bytes.
                form.Send += Form_Send;

                //STEP 4: Who's your daddy?!!
                form.MdiParent = this.MdiParent;


                form.Show();
                //if (form.ShowDialog() != DialogResult.OK) return;
            }
            catch (Exception exception)
            {
                MessageBoxUtilities.ShowException(exception);
            }
        }
예제 #11
0
        protected virtual void DoHighlighting()
        {
            //if (parser == null)
            //    return;

            //parse text
            ParseTree tree;

            try
            {
                tree = parser.Parse(Text);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message); //oops...
                return;
            }

            //highlight errors
            if (tree.Status == ParseTreeStatus.Error)

            {
                ClearStyle(GetStyleIndexMask(new Style[] { WavyStyle }));
                foreach (var msg in tree.ParserMessages)
                {
                    var loc   = msg.Location;
                    var place = new Place(loc.Column, loc.Line);
                    var r     = new Range(this, place, place);
                    var f     = r.GetFragment(@"[\S]");
                    f.SetStyle(WavyStyle);
                }
                return;
            }



            //highlight syntax
            ClearStyle(StyleIndex.All);
            foreach (var t in tree.Tokens)
            {
                var arg = new StyleNeededEventArgs(t);
                OnStyleNeeded(arg);

                if (arg.Cancel)
                {
                    continue;
                }

                if (arg.Style != null)
                {
                    GetTokenRange(t).SetStyle(arg.Style);
                    continue;
                }



                switch (t.Terminal.Name)
                {
                case "INTERVAL":     //Sample of how to color a single TOKEN, not working yet
                    GetTokenRange(t).SetStyle(SyntaxHighlighter.FunctionsStyle);
                    break;

                case "Identifier":
                    //GetTokenRange(t).SetStyle(SyntaxHighlighter.VariableStyle);
                    //Identifier: Discover the correct type for identifier and hihglight.
                    int CPIndex   = 0;
                    var IdentType = CoderHelper.GetTypeIdentifier(Identifiers, t.Text, out CPIndex);
                    switch (IdentType)
                    {
                    case PCODE_CONST.OUTPOINTTYPE:
                        GetTokenRange(t).SetStyle(SyntaxHighlighter.OutputStyle);
                        break;

                    case PCODE_CONST.INPOINTTYPE:
                        GetTokenRange(t).SetStyle(SyntaxHighlighter.InputStyle);
                        break;

                    case PCODE_CONST.VARPOINTTYPE:
                        GetTokenRange(t).SetStyle(SyntaxHighlighter.VariableStyle);
                        break;

                    case PCODE_CONST.PIDPOINTTYPE:
                        GetTokenRange(t).SetStyle(SyntaxHighlighter.PidStyle);
                        break;

                    default:
                        GetTokenRange(t).SetStyle(SyntaxHighlighter.VariableStyle);
                        break;
                    }
                    break;

                case "INS":
                    GetTokenRange(t).SetStyle(SyntaxHighlighter.InputStyle);
                    break;

                case "OUTS":
                    GetTokenRange(t).SetStyle(SyntaxHighlighter.OutputStyle);
                    break;

                case "VARS":
                    GetTokenRange(t).SetStyle(SyntaxHighlighter.VariableStyle);
                    break;

                case "PIDS":
                    GetTokenRange(t).SetStyle(SyntaxHighlighter.PidStyle);
                    break;

                case "LineNumber":
                    GetTokenRange(t).SetStyle(SyntaxHighlighter.InnerLinesNumberStyle);
                    break;

                default:     //parse by type: General highlighting
                    switch (t.Terminal.GetType().Name)
                    {
                    case "KeyTerm":
                        if ((t.Terminal.Flags & TermFlags.IsKeyword) != 0)         //keywords are highlighted only
                        {
                            GetTokenRange(t).SetStyle(SyntaxHighlighter.KeywordStyle);
                        }
                        break;

                    case "FreeTextLiteral":
                        GetTokenRange(t).SetStyle(SyntaxHighlighter.CommentStyle);
                        break;

                    case "NumberLiteral":
                        GetTokenRange(t).SetStyle(SyntaxHighlighter.NumberStyle);
                        break;

                    case "StringLiteral":
                        GetTokenRange(t).SetStyle(SyntaxHighlighter.StringStyle);
                        break;

                    case "CommentTerminal":
                        GetTokenRange(t).SetStyle(SyntaxHighlighter.CommentStyle);
                        break;
                    }
                    break;
                }
            }
        }
예제 #12
0
        ICoder <IEnumerable <ModelMeta> > GenSerializeCoder(bool isClient)
        {
            // [FieldIndex(Index = 1)]
            // public UInt32 TowerId;
            var fieldDec =
                "[FieldIndex(Index = {0})]".Basic <FieldMeta>(meta => meta.SerializeIndex)
                .Satisfy(meta => meta.SerializeIndex > 0 && !isClient)
                .SkipLine()
                .Append("public {0} {1};".Basic <FieldMeta>(meta => CoderHelper.GetTypeStr(meta.Field.FieldType),
                                                            meta => meta.Field.Name))
                .Satisfy(meta => !meta.IsInherit);

            var fieldWriterWithCheck =
                CoderHelper.WriteWithCheckCoder <FieldMeta>()
                .Lift(
                    (FieldMeta meta) =>
                    new Tuple <Type, ICoder <FieldMeta>, FieldMeta>(meta.Type, "{0}".Basic <FieldMeta>(f => f.Name),
                                                                    meta));

            var writer =
                Generator.GenSelect(
                    "public void Write(BinaryWriter bw)".Unit <ModelMeta>()
                    .Combine(fieldWriterWithCheck.Many("\n").Brace(), meta => meta.Fields)
                    .Satisfy(meta => !meta.IsHierarchy)
                    ,
                    "public {0} void Write(BinaryWriter bw)".Basic <ModelMeta>(meta =>
                                                                               Generator.GenSelect(
                                                                                   "override".Unit <ModelMeta>().Satisfy(meta1 => !meta1.IsTopmostBase)
                                                                                   , "virtual".Unit <ModelMeta>()).Code(meta))
                    .Append(
                        "bw.Write((byte){0});".Basic <ModelMeta>(meta => meta.HierarchyCode)
                        .Combine(fieldWriterWithCheck.Many("\n"), meta => meta.Fields)
                        .Brace()));

            var fieldReaderWithCheck =
                CoderHelper.ReadWithCheckCoder <FieldMeta>()
                .Lift(
                    (FieldMeta meta) =>
                    new Tuple <Type, ICoder <FieldMeta>, FieldMeta>(meta.Type, "{0}".Basic <FieldMeta>(f => f.Name),
                                                                    meta));

            var reader =
                Generator.GenSelect(
                    "public {0} Read(BinaryReader br)".Basic <ModelMeta>(meta => CoderHelper.GetTypeStr(meta.Type)).Satisfy(meta => !meta.IsHierarchy)
                    , "public new {0} ReadImpl(BinaryReader br)".Basic <ModelMeta>(meta => CoderHelper.GetTypeStr(meta.Type)))
                .Combine(fieldReaderWithCheck.Many("\n").Append("return this;".Unit <IEnumerable <FieldMeta> >()).Brace(), meta => meta.Fields);

            var hierarchyReader =
                "public new {0} Read(BinaryReader br){{return ({0})ReadStatic(br);}}".Basic <ModelMeta>(
                    meta => CoderHelper.GetTypeStr(meta.Type)).Satisfy(meta => meta.IsHierarchy);

            var topmostReaderDispatcher =
                "public static {0} ReadStatic(BinaryReader br)".Basic <ModelMeta>(
                    meta => CoderHelper.GetTypeStr(meta.Type))
                .Append(
                    "byte tp = br.ReadByte();if (tp != (byte)SerializeObjectMark.IsNull){{switch (tp){{{0}{1}}}}}return null;"
                    .Basic <ModelMeta>(meta => "case {0}: return (new {1}()).ReadImpl(br);".Basic <ModelMeta>(
                                           metac => metac.HierarchyCode, metac => CoderHelper.GetTypeStr(metac.Type))
                                       .Many("\n")
                                       .Code(meta.Children), meta => "default: return (new {0}()).ReadImpl(br);".Basic <ModelMeta>(metai => CoderHelper.GetTypeStr(metai.Type)).Code(meta)).Brace());

            var dumpAtomic =
                Generator.GenSelect(
                    "{0}!=null?string.Join(\", \", Array.ConvertAll({0}, input => input.ToString())):\"null\"".Basic <FieldMeta>(
                        meta => meta.Field.Name).Satisfy(meta => meta.Field.FieldType.IsArray)
                    ,
                    "{0}!=null?string.Join(\", \", Array.ConvertAll({0}.ToArray(), input => input.ToString())):\"null\"".Basic <FieldMeta>(
                        meta => meta.Field.Name).Satisfy(meta => meta.Field.FieldType.Name.Equals("List`1"))
                    ,
                    "{0}".Basic <FieldMeta>(meta => meta.Field.Name));

            var dumpHelpAtomic = "{0}={{{1}}}\\n".Basic <FieldMeta>(meta => meta.Field.Name, meta => meta.Position - 1);

            var dump =
                "public override string ToString(){{return string.Format(\"{0}:\\n{1}\", {2});}}"
                .Basic <ModelMeta>(meta => meta.Type.Name, meta => dumpHelpAtomic.Many("").Code(meta.Fields),
                                   meta => dumpAtomic.Many(",").Code(meta.Fields));

            var serialize =
                "public class {0}{1}{{".Basic <ModelMeta>(meta => meta.Type.Name, meta => ":{0}".Basic <ModelMeta>(meta1 => CoderHelper.GetTypeStr(meta1.Parent.Type)).Satisfy(meta1 => meta1.Parent != null).Code(meta))
                .Combine(fieldDec.Many("\n"), meta => meta.Fields)
                .Append(writer.SkipLine())
                .Append(reader.SkipLine())
                .Append(hierarchyReader.SkipLine().Satisfy(meta => meta.IsHierarchy))
                .Append(topmostReaderDispatcher.SkipLine().Satisfy(meta => meta.IsTopmostBase))
                .Append(dump.SkipLine())
                .WithPostfix("}");

            return(serialize.Many("\n"));
            //return "".Unit<TypeMeta>().Combine(dumpAtomic.Many(","), meta => meta.Fields).Many("\n");
        }
예제 #13
0
        ICoder <IEnumerable <ModelMeta> > GenDataAccessCoder()
        {
            Func <FieldMeta, bool> isKey = meta => meta.ModelMeta.Key == meta;
            var loadFieldMethodName      =
                "Load{0}At{1}Async".Basic <FieldMeta>(meta => meta.Name, meta => meta.ModelMeta.Name);
            var updateFieldMethodName =
                "Update{0}At{1}".Basic <FieldMeta>(meta => meta.Name, meta => meta.ModelMeta.Name);

            var fieldPara =
                "{0} {1}".Basic <FieldMeta>(meta => CoderHelper.GetTypeStr(meta.Type), meta => meta.Name.ToLower());
            var modelFieldPara =
                "{0} {1}".Basic <ModelMeta>(meta => CoderHelper.GetTypeStr(meta.Type), meta => meta.Name.ToLower());

            // Task<uint> LoadUidAtPlayerInfoAsync()
            var loadField =
                "{0} {1}()".Basic <FieldMeta>(meta => CoderHelper.TaskTypeCoder().Code(meta.Type),
                                              loadFieldMethodName.Code);

            // void UpdateUidAtPlayerInfo(uint uid)
            var updateField =
                "void {0}({1})".Basic <FieldMeta>(updateFieldMethodName.Code, meta => fieldPara.Code(meta));

            // Task<PlayerInfo> LoadPlayerInfoAsync(ulong pid)
            var loadModel =
                "{0} Load{1}Async()".Basic <FieldMeta>(meta => CoderHelper.TaskTypeCoder().Code(meta.ModelMeta.Type),
                                                       meta => meta.ModelMeta.Name);

            // void UpdatePlayerInfo(PlayerInfo info)
            var updateModel =
                "void Update{0}({1})".Basic <FieldMeta>(meta => meta.ModelMeta.Name, meta => modelFieldPara.Code(meta.ModelMeta));

            // ISessionReader
            var readInterfaceName = "I{0}Reader".Basic <ModelMeta>(meta => meta.Name);
            // ISessionAccesser
            var accessInterfaceName = "I{0}Accesser".Basic <ModelMeta>(meta => meta.Name);

            // public interface ISessionReader : IDisposable{...}
            var readInterface = "public interface {0}: IDisposable"
                                .Basic <ModelMeta>(meta => readInterfaceName.Code(meta))
                                .Combine(
                Generator.GenSelect(loadModel.Satisfy(isKey), loadField)
                .Statement()
                .Many("\n")
                .Brace()
                , meta => meta.Fields);

            // public interface ISessionAccesser : ISessionReader, ISubmitChangable{...}
            var accessInterface = "public interface {0}: {1}, ISubmitChangable"
                                  .Basic <ModelMeta>(meta => accessInterfaceName.Code(meta), meta => readInterfaceName.Code(meta))
                                  .Combine(
                Generator.GenSelect(updateModel.Satisfy(isKey), updateField)
                .Statement()
                .Many("\n")
                .Brace()
                , meta => meta.Fields);

            var modelAllFields =
                "#region {0}".Basic <ModelMeta>(meta => meta.Name)
                .SkipLine()
                .Combine(
                    Generator.GenSelect(loadModel.Satisfy(isKey), loadField)
                    .Statement()
                    .Many("\n")
                    ,
                    meta => meta.Fields)
                .Combine(
                    Generator.GenSelect(updateModel.Satisfy(isKey), updateField)
                    .Statement()
                    .Many("\n")
                    ,
                    meta => meta.Fields)
                .SkipLine()
                .WithPostfix("#endregion\n");

            // var val = new PlayerInfo();
            // var val = default(UInt);
            var val =
                Generator.GenSelect(
                    "var val = default({0});".Basic <Type>(CoderHelper.GetTypeStr).Satisfy(meta => meta.IsPrimitive || meta == typeof(string) || meta.IsArray)
                    //, "byte[] val = null;".Unit<Type>().Satisfy(meta=>meta == typeof(byte[]))
                    , "var val = new {0}();".Basic <Type>(CoderHelper.GetTypeStr));

            // default(T) / null
            var failVal =
                Generator.GenSelect(
                    "default({0})".Basic <Type>(CoderHelper.GetTypeStr).Satisfy(meta => meta.IsPrimitive || meta == typeof(string) || meta.IsEnum)
                    , "null".Unit <Type>());

            // reader.ReadField<UInt64>("Pid");/(TowerState)reader.ReadField<Int32>("Test");
            var readField =
                Generator.GenSelect(
                    "({0})reader.ReadField<Int32>(\"{1}\");".Basic <FieldMeta>(meta => CoderHelper.GetTypeStr(meta.Type), meta => meta.Name).Satisfy(meta => meta.Type.IsEnum)
                    , "reader.ReadField<{0}>(\"{1}\");".Basic <FieldMeta>(meta => CoderHelper.GetTypeStr(meta.Type), meta => meta.Name));

            // val = reader.ReadField<UInt64>("Pid");
            var fieldReadField =
                "val = {0}".Basic <FieldMeta>(readField.Code);

            // val.Pid = reader.ReadField<UInt64>("Pid");
            var modelReadField =
                "val.{0} = {1}".Basic <FieldMeta>(meta => meta.Name, readField.Code);

            // val.Pid = (ulong)key;
            var modelReadKeyField =
                "val.{0} = ({1})key;".Basic <FieldMeta>(meta => meta.Name, meta => CoderHelper.GetTypeStr(meta.Type));

            var fieldReader =
                Generator.GenSelect(
                    "".Unit <FieldMeta>()
                    .Combine(Generator.GenSelect(modelReadKeyField.Satisfy(isKey), modelReadField).Many("\n"), meta => meta.ModelMeta.Fields)
                    .Satisfy(isKey)
                    , fieldReadField);

            var fieldModelGetter =
                "(Int32)".Unit <FieldMeta>().Satisfy(meta => meta.Type.IsEnum)
                .Append("{1}.{0}".Basic <FieldMeta>(meta => meta.Name, meta => meta.ModelMeta.Name.ToLower()));

            var fieldGetter =
                "(Int32)".Unit <FieldMeta>().Satisfy(meta => meta.Type.IsEnum)
                .Append("{0}".Basic <FieldMeta>(meta => meta.Name.ToLower()));

            // .WriteField("InfoSkill", infoskill)
            var writeField =
                ".WriteField(\"{0}\", {1})".Basic <FieldMeta>(meta => meta.Name, fieldGetter.Code);

            // .WriteField("{0}", ({1})key)
            var writeKey =
                ".WriteField(\"{0}\", ({1})key)".Basic <FieldMeta>(meta => meta.Name, meta => CoderHelper.GetTypeStr(meta.Type));

            // .WriteField("Pid", playerinfo.Pid)
            var writeFieldModel =
                ".WriteField(\"{0}\", {1})".Basic <FieldMeta>(meta => meta.Name, fieldModelGetter.Code);

            Func <bool, ICoder <FieldMeta> > writer =
                isRedis =>
            {
                return("var ctx =  adaptor.Update(dataId);\n\nctx".Unit <FieldMeta>()
                       .SkipLine()
                       .Append(Generator.GenSelect(
                                   "".Unit <FieldMeta>().Combine(Generator.GenSelect(
                                                                     writeFieldModel.Satisfy(isKey), writeFieldModel).Many("\n"),
                                                                 meta => meta.ModelMeta.Fields).Satisfy(isKey)
                                   ,
                                   "{0}".Basic <FieldMeta>(meta => writeKey.Code(meta.ModelMeta.Key))
                                   .SkipLine().Satisfy(meta => !isRedis)
                                   .Append(writeField)))
                       .SkipLine()
                       .Append(
                           ";\nupdateQueue.Add(ctx);".Unit <FieldMeta>()));
            };

            var updateSig = Generator.GenSelect(updateModel.Satisfy(isKey), updateField).WithPrefix("public ");
            var loadSig   = Generator.GenSelect(loadModel.Satisfy(isKey), loadField).WithPrefix("public async ");

            #region redis

            // var dataId = string.Format("player:{0}", id);
            var key =
                "var dataId = string.Format(\"{0}:{{0}}\", {1});".Basic <FieldMeta>(
                    meta => meta.ModelMeta.RedisCacheName, meta => meta.ModelMeta.Key.Name.ToLower());

            var redisReader =
                Generator.GenSelect(
                    "var reader = await adaptor.QueryAll(dataId);if (reader == null){{return {0};}}".Basic <FieldMeta>(meta => failVal.Code(meta.ModelMeta.Type))
                    .Satisfy(isKey)
                    ,
                    "var reader = await adaptor.Query(dataId, \"{0}\");if (reader == null){{return {1};}}"
                    .Basic <FieldMeta>(meta => meta.Name, meta => failVal.Code(meta.Type)));

            var redisUpdateLast =
                "return await adaptor.UpdateWork({0});".Basic <FieldMeta>(meta => meta.ModelMeta.Key.Name.ToLower());

            var redisUpdate =
                updateSig.Append(
                    writer(true) /*.Append(redisUpdateLast)*/.Brace());

            var redisLoad =
                loadSig.Append(
                    Generator.GenSelect(
                        "{0}".Basic <FieldMeta>(meta => val.Code(meta.ModelMeta.Type)).Satisfy(isKey)
                        , "".Unit <FieldMeta>().Combine(val, meta => meta.Type)).Append(redisReader).Append(fieldReader).WithPostfix("return val;").Brace());

            var interfaceInherit =
                accessInterfaceName.Many(",");

            var delegateInnerRedisSpecial =
                @"public async Task<bool> SubmitChanges()
            {
                await adaptor.SubmitChanges(
        new[] { dataId }
      , new[] { contextLockId }
      , new [] {updateQueue});

                return true;
            }

            public async Task<bool> SubmitChangesWith(params object[] others)
            {
                await adaptor.SubmitChanges(
                    new[] { dataId } .Concat(others.Select(d => ((DelegateBase)d).dataId)).ToArray(),
                    new[] { contextLockId } .Concat(others.Select(d => ((DelegateBase)d).contextLockId)).ToArray(),
                    new[] { updateQueue } .Concat(others.Select(d => ((DelegateBase)d).updateQueue)).ToArray());

                return true;
            }

            public void Dispose()
            {

            }
".Unit();

            var redisDelegateInner =
                @"class Delegate<TKey> : DelegateBase, {0}
{{            
public Delegate(RedisAdaptor adaptor, long contextLockId, TKey key, string dataId)
            {{
                this.adaptor = adaptor;
                this.contextLockId = contextLockId;
                this.key = key;
                this.dataId = dataId;
            }}
            {2}
            private readonly RedisAdaptor adaptor;
            private readonly object key;

            {1}
}}"
                .Basic <IEnumerable <ModelMeta> >(
                    interfaceInherit.Code,
                    "#region {0}\n{1}\n#endregion\n".Basic <ModelMeta>(meta => meta.Name,
                                                                       meta => redisUpdate.Many("\n").SkipLine().Append(redisLoad.Many("\n")).Code(meta.Fields)).Many("\n").Code, delegateInnerRedisSpecial.Code);

            var modelReaderGetter =
                "public async Task<I{0}Reader> Get{0}Reader({1} {2}){{var dataId = string.Format(\"{3}:{{0}}\", {2});var lockId = 0;return new Delegate<{1}>(adaptor, lockId, {2}, dataId);}}"
                .Basic <ModelMeta>(
                    meta => meta.Name
                    , meta => CoderHelper.GetTypeStr(meta.Key.Type)
                    , meta => meta.Key.Name.ToLower()
                    , meta => meta.Name.ToLower());
            var modelAccesserGetter =
                "public async Task<I{0}Accesser> Get{0}Accesser({1} {2}){{var dataId = string.Format(\"{3}:{{0}}\", {2});var lockId = await adaptor.LockKey(dataId);return new Delegate<{1}>(adaptor, lockId, {2}, dataId);}}"
                .Basic <ModelMeta>(
                    meta => meta.Name
                    , meta => CoderHelper.GetTypeStr(meta.Key.Type)
                    , meta => meta.Key.Name.ToLower()
                    , meta => meta.Name.ToLower());

            var redisDelegate = "public class RedisDataServiceDelegate {{\n{0}\n{1}\n\nprivate readonly RedisAdaptor adaptor;public RedisDataServiceDelegate(RedisAdaptor adaptor){{this.adaptor = adaptor;}}\n }}"
                                .Basic <IEnumerable <ModelMeta> >(
                redisDelegateInner.Code
                , modelReaderGetter.SkipLine().Append(modelAccesserGetter).Many("\n").Code);

            #endregion

            #region mysql

            // `Pid`, `Uid`, `Name`, `Level`, `InfoSkill` ,`InfoItem`
            var fields =
                Generator.GenSelect(
                    "".Unit <FieldMeta>()
                    .Combine("`{0}`".Basic <FieldMeta>(meta => meta.Name).Many(","),
                             meta => meta.ModelMeta.Fields)
                    .Satisfy(meta => meta.ModelMeta.Key == meta)
                    , "`{0}`".Basic <FieldMeta>(meta => meta.Name));

            // const string sql = "SELECT `Pid`, `Uid`, `Name`, `Level`, `InfoSkill` ,`InfoItem` FROM `mem_player` WHERE `Pid` = ?1";
            var querySql =
                "const string sql = \"SELECT {0} FROM `{1}` WHERE `{2}` = ?1\";"
                .Basic <FieldMeta>(fields.Code, meta => meta.ModelMeta.MysqlTableName,
                                   meta => meta.ModelMeta.Key.Name);

            var mysqlReader =
                Generator.GenSelect(
                    "var reader = await adaptor.Query(sql, ({0})key);if (reader == null){{return {1};}}"
                    .Basic <FieldMeta>(meta => CoderHelper.GetTypeStr(meta.ModelMeta.Key.Type), meta => failVal.Code(meta.ModelMeta.Type))
                    .Satisfy(isKey)
                    ,
                    "var reader = await adaptor.Query(sql, ({0})key);if (reader == null){{return {1};}}"
                    .Basic <FieldMeta>(meta => CoderHelper.GetTypeStr(meta.ModelMeta.Key.Type), meta => failVal.Code(meta.Type)));

            var updateSqlKeyString =
                "INSERT INTO `{0}`({1}) VALUES({2}) ON DUPLICATE KEY UPDATE {3}".Basic <FieldMeta>(
                    meta => meta.ModelMeta.MysqlTableName
                    ,
                    "".Unit <FieldMeta>()
                    .Combine("`{0}`".Basic <FieldMeta>(meta => meta.Name).Many(","),
                             meta => meta.ModelMeta.Fields)
                    .Code
                    ,
                    "".Unit <FieldMeta>()
                    .Combine("?{0}".Basic <FieldMeta>(meta => meta.Position).Many(","),
                             meta => meta.ModelMeta.Fields)
                    .Code
                    ,
                    "".Unit <FieldMeta>()
                    .Combine(
                        "`{0}`=?{1}".Basic <FieldMeta>(meta => meta.Name, meta => meta.Position)
                        .Many(",", meta => !isKey(meta)), meta => meta.ModelMeta.Fields)
                    .Code);

            var updateSqlFieldString =
                "UPDATE `{0}` SET `{1}`=?2 WHERE `{2}`=?1".Basic <FieldMeta>(
                    meta => meta.ModelMeta.MysqlTableName, meta => meta.Name, meta => meta.ModelMeta.Key.Name);

            var updateSql =
                "const string dataId = \"{0}\"; ".Basic <FieldMeta>(Generator.GenSelect(
                                                                        updateSqlKeyString.Satisfy(isKey), updateSqlFieldString).Code);

            var mysqlUpdate =
                updateSig.Append(
                    Generator.GenSelect(
                        updateSql.Append(writer(false)).Satisfy(meta => meta.ModelMeta.MysqlTableName != null)
                        , "throw new Exception();".Unit <FieldMeta>())
                    .Brace());

            var mysqlLoad =
                loadSig.Append(
                    Generator.GenSelect(
                        querySql.Append(Generator.GenSelect(
                                            "{0}".Basic <FieldMeta>(meta => val.Code(meta.ModelMeta.Type)).Satisfy(isKey)
                                            , "".Unit <FieldMeta>().Combine(val, meta => meta.Type))).Append(mysqlReader).Append(fieldReader).WithPostfix("reader.Dispose();\nreturn val;").Satisfy(meta => meta.ModelMeta.MysqlTableName != null)
                        , "throw new Exception();".Unit <FieldMeta>())
                    .Brace());
            var delegateInnerMysqlSpecial =
                @"            public Task<bool> SubmitChanges()
            {
            throw new NotImplementedException();
            }

            public Task<bool> SubmitChangesWith(params object[] others)
            {
            throw new NotImplementedException();
            }

            public void Dispose()
            {

            }
".Unit();

            var mysqlDelegateInner =
                @"class Delegate<TKey> : {0}
{{            
public Delegate(MysqlAdaptor adaptor, TKey key)
            {{
                this.adaptor = adaptor;
                this.key = key;
            }}
            {2}
            private readonly MysqlAdaptor adaptor;
            private readonly object key;
            private readonly List<IUpdateDataContext> updateQueue = new List<IUpdateDataContext>();

            {1}
}}"
                .Basic <IEnumerable <ModelMeta> >(
                    accessInterfaceName.Many(",", m => m.MysqlTableName != null).Code,
                    "#region {0}\n{1}\n#endregion\n".Basic <ModelMeta>(meta => meta.Name,
                                                                       meta => mysqlUpdate.Many("\n").SkipLine().Append(mysqlLoad.Many("\n")).Code(meta.Fields)).Many("\n", m => m.MysqlTableName != null).Code, delegateInnerMysqlSpecial.Code);

            Func <string, ICoder <ModelMeta> > mysqlModelGetter = interfaceType =>
            {
                return(string.Format("public async Task<I{{0}}{0}> Get{{0}}{0}({{1}} {{2}}){{{{return new Delegate<{{1}}>(adaptor, {{2}});}}}}"
                                     , interfaceType)
                       .Basic <ModelMeta>(
                           meta => meta.Name
                           , meta => CoderHelper.GetTypeStr(meta.Key.Type)
                           , meta => meta.Key.Name.ToLower()
                           , meta => meta.Name.ToLower()));
            };

            var mysqlModelReaderGetter   = mysqlModelGetter("Reader");
            var mysqlModelAccesserGetter = mysqlModelGetter("Accesser");

            var mysqlDelegate = "public class MysqlDataServiceDelegate {{{0}\n{1}\n\nprivate readonly MysqlAdaptor adaptor;public MysqlDataServiceDelegate(MysqlAdaptor adaptor){{this.adaptor = adaptor;}}\n }}"
                                .Basic <IEnumerable <ModelMeta> >(
                mysqlDelegateInner.Code
                , mysqlModelReaderGetter.SkipLine().Append(mysqlModelAccesserGetter).Many("\n", m => m.MysqlTableName != null).Code);
            #endregion

            var genCoder =
                readInterface.SkipLine().Append(accessInterface).Many("\n")
                .SkipLine(2)
                .Append(redisDelegate)
                .SkipLine(2)
                .Append(mysqlDelegate);

            return(genCoder);
        }
        static ICoder <IEnumerable <ServiceMeta> > GenCoder(bool client)
        {
            #region name related
            // DbSyncNotify/LogicClient
            var serviceName = Generator.GenSelect(
                "{0}Notify".Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Type == ServiceType.Notify)
                , "{0}".Basic <ServiceMeta>(meta => meta.Name));

            // IDbSyncNotifyImpl
            var implName =
                "I{0}Impl".Basic <ServiceMeta>(meta => serviceName.Code(meta));

            // ILogicClientInvoke
            var invokeName =
                "I{0}Invoke".Basic <ServiceMeta>(meta => serviceName.Code(meta));

            // IClientLogicService
            var trivialServiceName =
                "I{0}Service".Basic <ServiceMeta>(meta => serviceName.Code(meta));

            // DbSyncNotifyDelegate/LoginNotifyDelegate
            var delegateName =
                Generator.GenSelect(
                    "{0}NotifyDelegate".Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Type == ServiceType.Notify)
                    , "{0}ServiceDelegate".Basic <ServiceMeta>(meta => meta.Name));

            // LoginNotifySerializer
            var serializerName =
                "{0}Serializer".Basic <ServiceMeta>(meta => serviceName.Code(meta));

            // LoginClientDispatcher
            var dispatcherName =
                "{0}Dispatcher".Basic <ServiceMeta>(meta => serviceName.Code(meta));

            // Task/Task<bool>
            var taskTypeName = Generator.GenSelect(
                "Task"
                .Unit <Type>()
                .Satisfy(meta => meta.Name.ToLower().Equals("void")),
                "Task<{0}>"
                .Basic <Type>(CoderHelper.GetTypeStr));

            // InvokeOperation/InvokeOperation<bool>
            var invokeTypeName = Generator.GenSelect(
                "InvokeOperation"
                .Unit <Type>()
                .Satisfy(meta => meta.Name.ToLower().Equals("void")),
                "InvokeOperation<{0}>"
                .Basic <Type>(CoderHelper.GetTypeStr));

            // InvokeOperation/InvokeOperation<bool>
            var invokeCallName = Generator.GenSelect(
                "Invoke"
                .Unit <Type>()
                .Satisfy(meta => meta.Name.ToLower().Equals("void")),
                "Invoke<{0}>"
                .Basic <Type>(CoderHelper.GetTypeStr));

            var invokeTaskCallName = Generator.GenSelect(
                "InvokeT"
                .Unit <Type>()
                .Satisfy(meta => meta.Name.ToLower().Equals("void")),
                "InvokeT<{0}>"
                .Basic <Type>(CoderHelper.GetTypeStr));
            #endregion

            #region function related
            // ulong pid
            var paraSig =
                "{0} {1}".Basic <ParameterMeta>(meta => CoderHelper.GetTypeStr(meta.Type), meta => meta.Name);
            // ulong pid, string newName
            var parasSig = Generator.GenSelect(
                paraSig.Many(",").Satisfy(meta => meta.Any())
                , "".Unit <IEnumerable <ParameterMeta> >().Satisfy(meta => !meta.Any()));

            // SyncPositionMulticast(int groupId, Int32 x, Int32 y)
            var methodMulticast = " {0}(int groupId, {1});".Basic <MethodMeta>(meta => meta.Name,
                                                                               meta => parasSig.Code(meta.Parameters));

            // AskChangeName(UInt64 pid, String newName);
            var methodWithoutReturnType = " {0}({1});".Basic <MethodMeta>(meta => meta.Name,
                                                                          meta => parasSig.Code(meta.Parameters));

            // Task<bool> AskChangeName(ulong pid, string newName);
            var taskMethod =
                methodWithoutReturnType.CombineReverse(taskTypeName, meta => meta.ReturnType);

            // bool AskChangeName(ulong pid, string newName);
            var normalMethod =
                methodWithoutReturnType.CombineReverse(Generator.GenBasic <Type>(CoderHelper.GetTypeStr), meta => meta.ReturnType);

            // InvokeOperation<bool> AskChangeName(ulong pid, string newName);
            var invokeMethod =
                methodWithoutReturnType.CombineReverse(invokeTypeName, meta => meta.ReturnType);
            #endregion

            #region interface related
            // public interface ILogicClientInvoke{...}
            var invokeGenCoder = Generator.GenCombine(invokeName.WithPrefix("public interface "),
                                                      invokeMethod.Many("\n").Brace(), meta => meta.Methods).Satisfy(meta => meta.Scope == ServiceScope.ClientToServer);

            // public interface ILoginNotifyImpl{...}
            var serverImplGenCoder =
                implName
                .WithPrefix("public interface ")
                .WithPostfix(": IRpcImplInstnce")
                .Combine(taskMethod.Many("\n").Brace(), meta => meta.Methods)
                .Satisfy(meta => meta.Scope != ServiceScope.ServerToClient);

            // public interface IClientLoginImpl{...}
            var clientImplGenCoder =
                implName
                .WithPrefix("public interface ")
                .WithPostfix(": IRpcImplInstnce")
                .Combine(normalMethod.Many("\n").Brace(), meta => meta.Methods)
                .Satisfy(meta => meta.Scope == ServiceScope.ServerToClient);

            #endregion

            #region delegate

            #region meta data
            // public const uint NotifyLogicServerWorking = 2001;
            var methodId =
                "public const uint {0} = {1};".Basic <MethodMeta>(meta => meta.Name, meta => meta.Id);

            // #region meta data ... #endregion
            var metaGenCoder = methodId.Many("\n").Brace().WithPrefix("private static class MethodId").Region("meta data");
            #endregion

            #region constructor && forward
            //private readonly ServiceDelegateStub serviceDelegateStub;
            //public ClientLogicServiceDelegate(IDataSender dataSender)
            //{
            //    serviceDelegateStub = new ServiceDelegateStub(dataSender, ClientLogicSerializer.Instance, MetaData.GetServiceRoutingRule(AutoInit.ClientLogic));
            //    dataSender.RegisterDelegate(serviceDelegateStub, AutoInit.ClientLogic);
            //}
            var delegateConstructor =
                @"private readonly ServiceDelegateStub serviceDelegateStub;
                  public {0}(IDataSender dataSender)
                  {{serviceDelegateStub = new ServiceDelegateStub(dataSender, {1}.Instance, MetaData.GetServiceRoutingRule(AutoInit.{2}));
                    dataSender.RegisterDelegate(serviceDelegateStub, AutoInit.{2});}}
"
                .Basic <ServiceMeta>(meta => delegateName.Code(meta), meta => serializerName.Code(meta), meta => meta.Name);

            //private readonly string forwardKey;
            //private ClientLoginServiceDelegate(ServiceDelegateStub serviceDelegateStub, string forwardKey)
            //{
            //    this.forwardKey = forwardKey;
            //    this.serviceDelegateStub = serviceDelegateStub;
            //}
            //public ClientLoginServiceDelegate Forward(byte[] sessionId)
            //{
            //    return new ClientLoginServiceDelegate(serviceDelegateStub, new Guid(sessionId).ToString());
            //}
            var delegateForward =
                @"private readonly byte[] forwardKey;
                  private {0}(ServiceDelegateStub serviceDelegateStub, byte[] forwardKey)
                  {{this.forwardKey = forwardKey;this.serviceDelegateStub = serviceDelegateStub;}}
                  public {0} Forward(byte[] forwardId)
                  {{return new {0}(serviceDelegateStub, forwardId);}}
"
                .Basic <ServiceMeta>(
                    meta => delegateName.Code(meta)).Satisfy(meta => meta.Scope == ServiceScope.ServerToClient);

            var forwardKey =
                Generator.GenSelect(
                    "forwardKey".Unit <ServiceMeta>().Satisfy(meta => meta.Scope == ServiceScope.ServerToClient)
                    , "null".Unit());
            #endregion

            // notify delegate

            // public void ServerMessageOk()
            var invokeMethodServerSig =
                "public {0} {1}({2})".Basic <MethodMeta>(meta =>
            {
                if (meta.ReturnType == typeof(void))
                {
                    return("void");
                }
                else
                {
                    return("Task<" + CoderHelper.GetTypeStr(meta.ReturnType) + ">");
                }
            }, meta => meta.Name,
                                                         meta => parasSig.Code(meta.Parameters));

            // public InvokeOperation<Boolean> AskLogin(UInt64 pid)
            var invokeMethodClientSig =
                "public {0} {1}({2})".Basic <MethodMeta>(meta => invokeTypeName.Code(meta.ReturnType), meta => meta.Name,
                                                         meta => parasSig.Code(meta.Parameters));

            // pid, newName
            var parasCall =
                "{0}".Basic <ParameterMeta>(meta => meta.Name).Many(",");

            var comma = Generator.GenSelect(
                ",".Unit <List <ParameterMeta> >().Satisfy(meta1 => meta1.Count > 0)
                , "".Unit <List <ParameterMeta> >().Satisfy(meta1 => meta1.Count == 0));

            // MethodId.AskChangeName, forwardKey, pid, newName
            var invokeCall =
                "MethodId.{0}, {1}{2}{3}".Basic <MethodMeta>(meta => meta.Name, meta => forwardKey.Code(meta.ServiceMeta), meta => comma.Code(meta.Parameters),
                                                             meta => parasCall.Code(meta.Parameters));

            // server to client delegate && notify delegate
            // serviceDelegateStub.Notify(MethodId.NotifyLogicServerWorking, null, districts);
            var invokeNoReturnBody = Generator.GenSelect(
                "serviceDelegateStub.Notify{0};".Basic <MethodMeta>(meta => invokeCall.Bracket().Code(meta)).Satisfy(
                    meta => meta.ServiceMeta.Type == ServiceType.Notify || meta.ServiceMeta.Type == ServiceType.Sync),
                "return serviceDelegateStub.{0}{1};".Basic <MethodMeta>(meta => invokeTaskCallName.Code(meta.ReturnType),
                                                                        meta => invokeCall.Bracket().Code(meta))
                );

            var multicastDelegate =
                "public void {0}Multicast(int groupId{1} {2})"
                .Basic <MethodMeta>(meta => meta.Name, meta => comma.Code(meta.Parameters),
                                    meta => parasSig.Code(meta.Parameters))
                .Append(
                    "serviceDelegateStub.Multicast(MethodId.{0}, groupId{1} {2});"
                    .Basic <MethodMeta>(meta => meta.Name, meta => comma.Code(meta.Parameters),
                                        meta => parasCall.Code(meta.Parameters)).Brace());

            // return serviceDelegateStub.Invoke<Boolean>(MethodId.AskAddMoney, null, pid, money);
            var invokeClientBody =
                "return serviceDelegateStub.{0}{1};".Basic <MethodMeta>(meta => invokeCallName.Code(meta.ReturnType),
                                                                        meta => invokeCall.Bracket().Code(meta));


            //public void NotifyPlayerLoaded(UInt64 pid){this.Task(methodNotifyPlayerLoaded, pid);}
            var invokeNoReturnMethodGen = Generator.GenFunction(invokeMethodServerSig, invokeNoReturnBody, Generator.Id);
            var invokeClientMethodGen   = Generator.GenFunction(invokeMethodClientSig, invokeClientBody, Generator.Id);

            var delegateMethod =
                Generator.GenSelect(
                    invokeClientMethodGen.Satisfy(
                        meta => meta.ServiceMeta.Scope == ServiceScope.ClientToServer && client)
                    , invokeNoReturnMethodGen);

            var delegateCoder =
                "public class {0}".Basic <ServiceMeta>(meta => delegateName.Code(meta))
                .Append(": {0}".Basic <ServiceMeta>(meta => invokeName.Code(meta))
                        .Satisfy(meta => meta.Scope == ServiceScope.ClientToServer && client))
                .Append(delegateConstructor.Append(delegateForward)
                        .Combine(metaGenCoder, meta => meta.Methods)
                        .Combine(delegateMethod.Many("\n"), meta => meta.Methods)
                        .Combine(multicastDelegate.Satisfy(meta => meta.ServiceMeta.Multicast && !client).Many("\n"), meta => meta.Methods).Brace());

            #endregion

            // case 1001:
            var label = "case {0}:".Basic <MethodMeta>(meta => meta.Id);

            #region dispatcher

            // (ulong)method.Args[0]
            var unboxedArg =
                "({0})(method.Args[{1}])".Basic <ParameterMeta>(meta => CoderHelper.GetTypeStr(meta.Type),
                                                                meta => meta.Position);

            // (UInt64)method.Args[0], (String)method.Args[1]
            var unboxedArgs = unboxedArg.Many(",");

            // AskChangeName((UInt64)method.Args[0], (String)method.Args[1])
            var dispatchMethod =
                "{0}".Basic <MethodMeta>(meta => meta.Name).Combine(unboxedArgs.Bracket(), meta => meta.Parameters);

            // public static readonly ClientLogicDispatcher Instance = new ClientLogicDispatcher();
            var dispatcherSingleton =
                "public static readonly {0} Instance = new {0}();"
                .Basic <ServiceMeta>(meta => dispatcherName.Code(meta));

            // (IDbSyncNotifyImpl)impl
            var implConvert =
                "({0})impl".Basic <ServiceMeta>(meta => implName.Code(meta));

            // ((IDbSyncNotifyImpl)impl).NotifyPlayerLoaded((UInt64)method.Args[0])
            var dispatchCall =
                "({0}).{1}".Basic <MethodMeta>(meta => implConvert.Code(meta.ServiceMeta),
                                               meta => dispatchMethod.Code(meta));

            //  case 4001:
            //  ((ILoginClientImpl)impl).AskLogin((string)method.Args[0], (byte[])method.Args[1]).ContinueWith(t => DoContinue(t, cont));
            //  break;
            //  case 5001:
            //  ((IClientLogicImpl)impl).ServerMessageOk();
            //  break;
            var dispatchSwitch =
                label.Append(
                    Generator.GenSelect(
                        "{0}.ContinueWith(t=>DoContinue(t, cont));".Basic <MethodMeta>(meta => dispatchCall.Code(meta)).Satisfy(meta => meta.ServiceMeta.Scope != ServiceScope.ServerToClient && meta.ServiceMeta.Type != ServiceType.Notify)
                        , "{0};".Basic <MethodMeta>(meta => dispatchCall.Code(meta))))
                .Append("break;".Unit <MethodMeta>());

            var dispatchMethodAll =
                "public void Dispatch(IRpcImplInstnce impl, RpcMethod method, ServiceImplementStub.SendResult cont)"
                .Unit <ServiceMeta>()
                .Append(
                    "switch (method.MethodId)"
                    .Unit <ServiceMeta>()
                    .Combine(
                        dispatchSwitch.Many("\n").Brace(), meta => meta.Methods)
                    .Brace());

            var dispatcherCoder =
                "public class {0} : "
                .Basic <ServiceMeta>(meta => dispatcherName.Code(meta))
                .Append("ServiceMethodDispatcherEx, ".Unit <ServiceMeta>().Satisfy(meta => !client))
                .Append("IServiceMethodDispatcher".Unit <ServiceMeta>())
                .Append(
                    dispatcherSingleton.Append(dispatchMethodAll).Brace());

            #endregion

            #region serializer

            // public static readonly ClientLogicSerializer Instance = new ClientLogicSerializer();
            var serializerSingleton =
                "public static readonly {0} Instance = new {0}();"
                .Basic <ServiceMeta>(meta => serializerName.Code(meta));

            var methodArgsGetter = "method.Args[{0}]".Basic <ParameterMeta>(meta => meta.Position);
            var argsGetter       = "args[{0}]".Basic <ParameterMeta>(meta => meta.Position, meta => CoderHelper.GetTypeStr(meta.Type));

            var readArgCheck =
                CoderHelper.ReadWithCheckCoder <ParameterMeta>()
                .Lift(
                    (ParameterMeta meta) =>
                    new Tuple <Type, ICoder <ParameterMeta>, ParameterMeta>(meta.Type, methodArgsGetter, meta));

            var writeArgCheck =
                CoderHelper.WriteWithCheckCoder <ParameterMeta>()
                .Lift(
                    (ParameterMeta meta) =>
                    new Tuple <Type, ICoder <ParameterMeta>, ParameterMeta>(meta.Type, argsGetter, meta));

            var readSwitch =
                label
                .Append(
                    "method.Args = new object[{0}];".Basic <MethodMeta>(meta => meta.Parameters.Count).Satisfy(meta => meta.Parameters.Count > 0)
                    .Combine(readArgCheck.Many("\n"), meta => meta.Parameters))
                //.Append(
                //    "method.NeedReturn = true;"
                //    .Unit<MethodMeta>()
                //    .Satisfy(meta => meta.ServiceMeta.Type == ServiceType.Service))
                .Append(
                    "break;".Unit <MethodMeta>());

            var readDispatchGen =
                "public RpcMethod Read(BinaryReader br)".Unit <ServiceMeta>()
                .Append(
                    "RpcMethod method = new RpcMethod();\nmethod.MethodId = br.ReadUInt32();\n".Unit <ServiceMeta>()
                    .Append(
                        "switch (method.MethodId)".Unit <ServiceMeta>()
                        .Combine(
                            readSwitch.Many("\n").Brace(), meta => meta.Methods))
                    .Append(
                        "return method;".Unit <ServiceMeta>()).Brace());

            var writeSwitch =
                label
                .Combine(
                    writeArgCheck.Many("\n").WithPostfix("break;").Brace(), meta => meta.Parameters);

            var writeDispatchGen =
                "public void Write(uint methodId, object[] args, BinaryWriter bw)"
                .Unit <ServiceMeta>()
                .Append(
                    "bw.Write(methodId);\n"
                    .Unit <ServiceMeta>()
                    .Append("switch (methodId)"
                            .Unit <ServiceMeta>()
                            .Combine(
                                writeSwitch.Many("\n").Brace(), meta => meta.Methods)).Brace());

            var readReturnWithCheck =
                CoderHelper.ReadWithCheckCoder <MethodMeta>()
                .Lift(
                    (MethodMeta meta) =>
                    new Tuple <Type, ICoder <MethodMeta>, MethodMeta>(meta.ReturnType, "returnVal".Unit <MethodMeta>(), meta));

            var readReturnSwitch =
                label
                .Append(readReturnWithCheck.WithPostfix("break;").Brace()).Satisfy(meta => meta.ReturnType != typeof(void));

            var readReturnDispatch =
                "public object ReadReturn(uint methodId, BinaryReader br)".Unit <ServiceMeta>()
                .Append(
                    (
                        ("var returnVal = new object();\n").Unit <ServiceMeta>()
                        .Append(
                            "switch (methodId)".Unit <ServiceMeta>()
                            .Combine(readReturnSwitch.Many("\n").Brace(), meta => meta.Methods)
                            .Satisfy(meta => meta.Methods.Any(m => m.ReturnType != typeof(void))))
                        .Append("return returnVal;".Unit <ServiceMeta>())
                        .Brace()
                    ));

            var writeValueWithCheck =
                CoderHelper.WriteWithCheckCoder <MethodMeta>()
                .Lift(
                    (MethodMeta meta) =>
                    new Tuple <Type, ICoder <MethodMeta>, MethodMeta>(meta.ReturnType, "value".Unit <MethodMeta>(), meta));

            var writeReturnSwitch =
                label
                .Append(writeValueWithCheck)
                .Append("break;".Unit <MethodMeta>())
                .Satisfy(meta => meta.ReturnType != typeof(void));

            var writeReturnDispatch =
                "public void WriteReturn(RpcMethod method, BinaryWriter bw, object value)".Unit <ServiceMeta>()
                .Append((
                            "switch (method.MethodId)".Unit <ServiceMeta>()
                            .Combine(
                                writeReturnSwitch.Many("\n").Brace(), meta => meta.Methods)).Satisfy(meta => meta.Methods.Any(m => m.ReturnType != typeof(void))).Brace());

            var serializerCoder =
                "public class {0} : IMethodSerializer".Basic <ServiceMeta>(meta => serializerName.Code(meta))
                .Append(
                    serializerSingleton
                    .Append(readDispatchGen.SkipLine())
                    .Append(writeDispatchGen.SkipLine())
                    .Append(readReturnDispatch.SkipLine())
                    .Append(writeReturnDispatch.SkipLine())
                    .Brace());
            #endregion

            #region serviceMeta

            var implMetaInit =
                @"MetaData.SetServiceId(typeof({0}), {1});
            MetaData.SetMethodSerializer(typeof({0}), {2}.Instance);
            MetaData.SetServiceMethodDispatcher(typeof({0}), {3}.Instance); "
                .Basic <ServiceMeta>(
                    meta => implName.Code(meta)
                    , meta => meta.Name
                    , meta => serializerName.Code(meta)
                    , meta => dispatcherName.Code(meta))
                .Satisfy(meta => (meta.Scope == ServiceScope.ServerToClient && client) || (meta.Scope != ServiceScope.ServerToClient && !client));

            var autoInitName =
                "internal const string {0} = \"{0}\";".Basic <ServiceMeta>(meta => meta.Name);

            var implBindingKey =
                Generator.GenSelect(
                    "ImplBindingKey = (districts, uuid) => \"padding.{0}.notify\",\n".Basic <ServiceMeta>(
                        meta => meta.Name)
                    .Satisfy(meta => meta.Type == ServiceType.Notify)
                    ,
                    "ImplBindingKey = (districts, uuid) => string.Format(\"{{0}}/{0}/sync/{{1}}\", districts, uuid),\n"
                    .Basic <ServiceMeta>(meta => meta.Name)
                    .Satisfy(
                        meta => meta.Type == ServiceType.Sync && meta.Scope == ServiceScope.ServerToClient && client)
                    ,
                    Generator.GenSelect(
                        "ImplBindingKey = (districts, uuid) => string.Format(\"{{0}}.{0}.invoke\", districts),\n"
                        .Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                        ,
                        "ImplBindingKey = (districts, uuid) => string.Format(\"padding.{0}.invoke\"),\n"
                        .Basic <ServiceMeta>(meta => meta.Name))
                    .Satisfy(meta => meta.Scope == ServiceScope.ClientToServer && !client)

                    ,
                    Generator.GenSelect(
                        Generator.GenSelect(
                            "ImplBindingKey = (districts, uuid) => string.Format(\"{{0}}.{0}.invoke\", districts),\n".Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                            , "ImplBindingKey = (districts, uuid) => string.Format(\"padding.{0}.invoke\", districts),\n".Basic <ServiceMeta>(meta => meta.Name)
                            ).Satisfy(meta => meta.Type == ServiceType.Service))
                    .Satisfy(meta => meta.Scope == ServiceScope.InterServer)

                    );

            var delegateRoutingKey =
                Generator.GenSelect(
                    "DelegateRoutingKey = (districts, fid) => \"padding.{0}.notify\",\n".Basic <ServiceMeta>(meta => meta.Name)
                    .Satisfy(meta => meta.Type == ServiceType.Notify)
                    ,
                    "DelegateRoutingKey = (districts, uuid) => string.Format(\"{{0}}.{0}.sync.{{1}}\", districts, uuid),\n".Basic <ServiceMeta>(meta => meta.Name)
                    .Satisfy(meta => meta.Type == ServiceType.Sync && meta.Scope == ServiceScope.ServerToClient && !client)
                    ,
                    Generator.GenSelect(
                        "DelegateRoutingKey = (districts, uuid) => string.Format(\"{{0}}/{0}/invoke\", districts),\n".Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                        , "DelegateRoutingKey = (districts, uuid) => string.Format(\"padding/{0}/invoke\"),\n".Basic <ServiceMeta>(meta => meta.Name))
                    .Satisfy(meta => meta.Scope == ServiceScope.ClientToServer && client)
                    , Generator.GenSelect(
                        Generator.GenSelect(
                            "DelegateRoutingKey = (districts, uuid) => string.Format(\"{{0}}.{0}.invoke\", districts),\n".Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                            , "DelegateRoutingKey = (districts, uuid) => string.Format(\"padding.{0}.invoke\", districts),\n".Basic <ServiceMeta>(meta => meta.Name)
                            ).Satisfy(meta => meta.Type == ServiceType.Service))
                    .Satisfy(meta => meta.Scope == ServiceScope.InterServer)
                    );

            var returnBindKey =
                Generator.GenSelect(
                    Generator.GenSelect(
                        "ReturnBindingKey = (districts, uuid) => string.Format(\"{{0}}/{0}/return/{{1}}\", districts, uuid),\n"
                        .Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                        ,
                        "ReturnBindingKey = (districts, uuid) => string.Format(\"padding/{0}/return/{{0}}\", uuid),\n"
                        .Basic <ServiceMeta>(meta => meta.Name))
                    .Satisfy(meta => meta.Scope == ServiceScope.ClientToServer && client)
                    , Generator.GenSelect(
                        Generator.GenSelect(
                            "ReturnBindingKey = (districts, uuid) => string.Format(\"{{0}}.{0}.return.{{1}}\", districts, uuid),\n"
                            .Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                            ,
                            "ReturnBindingKey = (districts, uuid) => string.Format(\"padding.{0}.return.{{1}}\", districts, uuid),\n"
                            .Basic <ServiceMeta>(meta => meta.Name)
                            ).Satisfy(meta => meta.Type == ServiceType.Service))
                    .Satisfy(meta => meta.Scope == ServiceScope.InterServer)

                    );

            var returnRoutingKey =
                Generator.GenSelect(
                    Generator.GenSelect(
                        "ReturnRoutingKey = (districts, uuid) => string.Format(\"{{0}}.{0}.return.{{1}}\", districts, uuid),\n"
                        .Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                        , "ReturnRoutingKey = (districts, uuid) => string.Format(\"padding.{0}.return.{{0}}\", uuid),\n"
                        .Basic <ServiceMeta>(meta => meta.Name))
                    .Satisfy(meta => meta.Scope == ServiceScope.ClientToServer && !client)
                    , Generator.GenSelect(
                        Generator.GenSelect(
                            "ReturnRoutingKey = (districts, uuid) => string.Format(\"{{0}}.{0}.return.{{1}}\", districts, uuid),\n"
                            .Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                            ,
                            "ReturnRoutingKey = (districts, uuid) => string.Format(\"padding.{0}.return.{{1}}\", districts, uuid),\n"
                            .Basic <ServiceMeta>(meta => meta.Name)
                            ).Satisfy(meta => meta.Type == ServiceType.Service))
                    .Satisfy(meta => meta.Scope == ServiceScope.InterServer));

            var returnExchange =
                Generator.GenSelect(
                    "ReturnExchangeName = () => \"amq.topic\",\n".Unit <ServiceMeta>()
                    .Satisfy(meta => meta.Scope == ServiceScope.ClientToServer && !client),
                    "ReturnExchangeName = () => \"{0}.return\",\n".Basic <ServiceMeta>(meta => meta.Name)
                    .Satisfy(meta => meta.Scope == ServiceScope.InterServer)
                    ).Satisfy(meta => meta.Type == ServiceType.Service);

            var delegateExchange =
                Generator.GenSelect(
                    "DelegateExchangeName = () => \"amq.topic\",\n".Unit <ServiceMeta>()
                    .Satisfy(meta => meta.Scope == ServiceScope.ServerToClient && !client)
                    ,
                    "DelegateExchangeName = () => \"{0}.notify\",\n".Basic <ServiceMeta>(meta => meta.Name)
                    .Satisfy(meta => meta.Type == ServiceType.Notify && !client)
                    ,
                    "DelegateExchangeName = () => \"{0}.invoke\",\n".Basic <ServiceMeta>(meta => meta.Name)
                    .Satisfy(meta => meta.Type == ServiceType.Service && meta.Scope == ServiceScope.InterServer && !client));

            var implExchange =
                Generator.GenSelect(
                    "ImplExchangeName = () => \"{0}.notify\",\n".Basic <ServiceMeta>(meta => meta.Name)
                    .Satisfy(meta => meta.Type == ServiceType.Notify && !client),
                    "ImplExchangeName = () => \"{0}.invoke\",\n".Basic <ServiceMeta>(meta => meta.Name)
                    .Satisfy(meta => meta.Type == ServiceType.Service && !client));

            var implQueueName =
                Generator.GenSelect(
                    "ImplQueueName = districts=>string.Format(\"{{0}}.{0}.invoke\", districts),\n"
                    .Basic <ServiceMeta>(
                        meta => serviceName.Code(meta)).Satisfy(meta => meta.Divisional)
                    , "ImplQueueName = districts => string.Format(\"padding.{0}.invoke\"),\n".Basic <ServiceMeta>(
                        meta => serviceName.Code(meta)))
                .Satisfy(meta => meta.Type == ServiceType.Service && !client);

            var publishKey =
                Generator.GenSelect(
                    "PublishKey = (districts, uuid) => string.Format(\"{{0}}/{0}/invoke\", districts),\n"
                    .Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                    ,
                    "PublishKey = (districts, uuid) => string.Format(\"padding/{0}/invoke\"),\n"
                    .Basic <ServiceMeta>(meta => meta.Name))
                .Satisfy(meta => meta.Scope == ServiceScope.ClientToServer && client);

            var subscribeKey =
                Generator.GenSelect(
                    "SubscribeKey = (districts, uuid) => string.Format(\"{{0}}/{0}/sync/{{1}}\", districts, uuid),\n"
                    .Basic <ServiceMeta>(meta => meta.Name)
                    .Satisfy(meta => meta.Type == ServiceType.Sync && meta.Scope == ServiceScope.ServerToClient && client)
                    ,
                    Generator.GenSelect(
                        "SubscribeKey = (districts, uuid) => string.Format(\"{{0}}/{0}/return/{{1}}\", districts, uuid),\n"
                        .Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                        ,
                        "SubscribeKey = (districts, uuid) => string.Format(\"padding/{0}/return/{{0}}\", uuid),\n"
                        .Basic <ServiceMeta>(meta => meta.Name))
                    .Satisfy(meta => meta.Scope == ServiceScope.ClientToServer && client));

            var zkServicePath =
                Generator.GenSelect(
                    "ServicePath = (districts) => string.Format(\"/{{0}}/{{1}}\", districts, {0}),\n"
                    .Basic <ServiceMeta>(meta => meta.Name).Satisfy(meta => meta.Divisional)
                    ,
                    "ServicePath = (districts) => string.Format(\"/global/{{1}}\", districts, {0}),\n"
                    .Basic <ServiceMeta>(meta => meta.Name));

            var gateServiceId =
                "ServiceId  = s => {0},"
                .Basic <ServiceMeta>(meta => meta.Id);

            var amqpRule =
                "AmqpRule = new RoutingRule.AmqpRoutingRule()"
                .Unit <ServiceMeta>()
                .Append(
                    implBindingKey
                    .Append(delegateRoutingKey)
                    .Append(returnBindKey)
                    .Append(returnRoutingKey)
                    .Append(returnExchange)
                    .Append(delegateExchange)
                    .Append(implExchange)
                    .Append(implQueueName)
                    .Brace()).WithPostfix(",");

            var mqttRule =
                "MqttRule = new RoutingRule.MqttRoutingRule()"
                .Unit <ServiceMeta>()
                .Append(
                    publishKey
                    .Append(subscribeKey)
                    .Brace()).WithPostfix(",");

            var gateRule =
                "GateRule = new RoutingRule.GateRoutingRule()"
                .Unit <ServiceMeta>()
                .Append(
                    gateServiceId
                    .Brace()).WithPostfix(",");

            var zkRule =
                "ZkRule = new RoutingRule.ZkRoutingRule()"
                .Unit <ServiceMeta>()
                .Append(
                    zkServicePath
                    .Brace()).WithPostfix(",");

            var metaBuilder =
                "MetaData.SetServiceRoutingRule({0}, new RoutingRule()"
                .Basic <ServiceMeta>(meta => meta.Name)
                .Append(
                    amqpRule.SkipLine().Satisfy(_ => !client)
                    .Append(mqttRule.SkipLine().Satisfy(_ => client))
                    .Append(gateRule.SkipLine())
                    .Append(zkRule.SkipLine().Satisfy(_ => !client))
                    .Brace().WithPostfix(");"));

            var metaConstructor =
                implMetaInit.Many("\n").Append(metaBuilder.Many("\n")).Brace().WithPrefix("\nstatic AutoInit()");

            var metaCoder =
                autoInitName.Many("\n")
                .Append(metaConstructor)
                .Append(
                    "public static void Init(){}".Unit <IEnumerable <ServiceMeta> >())
                .Brace().WithPrefix("\npublic static class AutoInit");
            #endregion

            var serviceCoder =
                invokeGenCoder.Satisfy(_ => client)
                .Append(clientImplGenCoder.Satisfy(meta => client).SkipLine())
                .Append(serverImplGenCoder.Satisfy(meta => !client).SkipLine())
                .Append(delegateCoder.Satisfy(meta => (meta.Scope == ServiceScope.ClientToServer && client) || (meta.Scope != ServiceScope.ClientToServer && !client)).WithPostfix("\n"))
                .Append(dispatcherCoder.Satisfy(meta => (meta.Scope != ServiceScope.ServerToClient && !client) || (meta.Scope == ServiceScope.ServerToClient && client)).WithPostfix("\n"))
                .Append(serializerCoder.SkipLine());

            var serviceWithRegion =
                "#region {0}\n{1}#endregion".Basic <ServiceMeta>(serviceName.Code, serviceCoder.Code);

            return
                (metaCoder.WithPostfix("\n")
                 .Append(serviceWithRegion.Many("\n")));
        }