public void GenerateCode(InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w)
        {
            var iname = idecl.Identifier.ToString();

            Console.WriteLine("GenerateCode: " + iname);

            w._($"#region {iname}");
            w._();

            var namespaceScope  = idecl.GetNamespaceScope();
            var namespaceHandle = (string.IsNullOrEmpty(namespaceScope) == false)
                                      ? w.B($"namespace {idecl.GetNamespaceScope()}")
                                      : null;

            var useProtoContract = idecl.AttributeLists.GetAttribute("ProtoContractAttribute") != null;

            GenerateTrackablePocoCode(idecl, w, useProtoContract);

            if (useProtoContract)
            {
                GenerateTrackablePocoSurrogateCode(idecl, w);
            }

            namespaceHandle?.Dispose();

            w._();
            w._($"#endregion");
        }
Ejemplo n.º 2
0
        private void GenerateTrackableContainerAot(InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w)
        {
            if (Utility.IsMessagePackObject(idecl.AttributeLists) == false)
            {
                return;
            }

            var typeName  = idecl.GetTypeName();
            var className = "Trackable" + typeName.Substring(1) + "Tracker";

            using (w.B($"public static class {className}AotWorkaround"))
            {
                using (w.B($"public static void TryAotWorkaround()"))
                {
                    using (w.b($"var aotLists = new List<object>"))
                    {
                        var properties = idecl.GetProperties();
                        foreach (var p in properties)
                        {
                            var propertyName = p.Identifier.ToString();
                            var trackerName  = Utility.GetMessagePackAot(p.Type);
                            w._($"{trackerName}");
                        }
                    }
                    w.Write(";");
                }
            }
        }
Ejemplo n.º 3
0
        public void GenerateCode(Type type, Dictionary <int, string> rpcEnumMap, CodeWriter.CodeWriter w)
        {
            Console.WriteLine("GenerateCode: " + type.GetSymbolDisplay(true));

            w._($"#region {type.GetSymbolDisplay(true)}");
            w._("#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS");
            w._();

            var namespaceHandle = (string.IsNullOrEmpty(type.Namespace) == false)
                ? w.B($"namespace {type.Namespace}")
                : null;

            var baseTypes = type.GetInterfaces().Where(t => t.FullName != "EuNet.Rpc.IViewRpc").ToArray();
            var infos     = new List <Tuple <Type, List <Tuple <MethodInfo, Tuple <string, string> > > > >();

            foreach (var t in new[] { type }.Concat(baseTypes))
            {
                var methods = GetInvokableMethods(t);
                var method2PayloadTypeNameMap = GetPayloadTypeNames(t, methods);
                infos.Add(Tuple.Create(t, GetPayloadTypeNames(t, methods)));
            }

            // Generate all

            GenerateRpcCode(type, w, baseTypes, infos.ToArray(), rpcEnumMap);
            GenerateRpcServiceCode(type, w, infos.First().Item2, infos.ToArray());
            GenerateRpcServiceViewCode(type, w, infos.First().Item2, infos.ToArray());

            namespaceHandle?.Dispose();

            w._();
            w._("#endif");
            w._($"#endregion");
        }
Ejemplo n.º 4
0
        private static void Main(string[] args)
        {
            var s = new CodeWriterSettings(CodeWriterSettings.CSharpDefault);

            s.NewLineBeforeBlockBegin = false;
            s.TranslationMapping["`"] = "\"";

            var w = new CodeWriter.CodeWriter(s);

            using (w.B("class Test"))
            {
                using (w.B("public int Sum(int a, int b)"))
                {
                    w._("var r = a + b;",
                        "return r;");
                }

                using (w.B("public int Mul(int a, int b)"))
                {
                    w._("var r = `a * b`;",
                        "return r;");
                }
            }
            w.HeadLines = new List <string>
            {
                "// COMMENT1",
                "// COMMENT2",
                "",
                "using System;",
                "",
            };

            Console.Write(w.ToString());
        }
Ejemplo n.º 5
0
        public void GenerateCode(Dictionary <int, string> rpcEnumMap, CodeWriter.CodeWriter w)
        {
            var rpcEnumNamespace = $"{Options.Namespace}";

            w._($"#region {rpcEnumNamespace}");
            w._();

            using (w.B($"namespace {rpcEnumNamespace}"))
            {
                using (w.B($"public static class RpcEnumHelper"))
                {
                    using (w.B("public static string GetEnumName(int rpcNameHash)"))
                    {
                        using (w.B($"switch(rpcNameHash)"))
                        {
                            foreach (var kvp in rpcEnumMap)
                            {
                                w._($"case {kvp.Key}: return \"{kvp.Value}\";");
                            }
                        }

                        w._($"return string.Empty;");
                    }
                }
            }

            w._();
            w._($"#endregion");
        }
Ejemplo n.º 6
0
        public void GenerateMethods(DbRowsetDeclaration d, CodeWriter.CodeWriter w)
        {
            using (w.B($"public async Task<Row> NextAsync()"))
            {
                w._($"if (await _reader.ReadAsync() == false) return null;",
                    $"var r = new Row();");

                var fidx = 0;
                foreach (var field in d.Fields)
                {
                    w._($"var v{fidx} = _reader.GetValue({fidx});");
                    if (field.Nullable)
                    {
                        var ntype = field.Type + (DbTypeHelper.IsValueType(field.Type) ? "?" : "");
                        w._($"r.{field.Name} = (v{fidx} is DBNull) ? ({ntype})null : ({field.Type})v{fidx};");
                    }
                    else
                    {
                        var ivalue = DbTypeHelper.GetInitValue(field.Type);
                        w._($"r.{field.Name} = (v{fidx} is DBNull) ? {ivalue} : ({field.Type})v{fidx};");
                    }
                    fidx += 1;
                }

                w._($"return r;");
            }

            using (w.B($"public async Task<List<Row>> FetchAllRowsAndDisposeAsync()"))
            {
                w._($"var rows = new List<Row>();");
                using (w.b($"while (true)"))
                {
                    w._($"var row = await NextAsync();",
                        $"if (row == null) break;",
                        $"rows.Add(row);");
                }
                w._($"Dispose();",
                    $"return rows;");
            }

            using (w.B($"public async Task<List<T>> FetchAllRowsAndDisposeAsync<T>(Func<Row, T> selector)"))
            {
                w._($"var rows = new List<T>();");
                using (w.b($"while (true)"))
                {
                    w._($"var row = await NextAsync();",
                        $"if (row == null) break;",
                        $"rows.Add(selector(row));");
                }
                w._($"Dispose();",
                    $"return rows;");
            }

            using (w.B($"public void Dispose()"))
            {
                w._($"_reader.Dispose();");
            }
        }
Ejemplo n.º 7
0
        public EntryCodeGenerator(Options options)
        {
            Options = options;

            var settings = new CodeWriterSettings(CodeWriterSettings.CSharpDefault);
            settings.TranslationMapping["`"] = "\"";
            CodeWriter = new CodeWriter.CodeWriter(settings);

            GenerateHead();
        }
Ejemplo n.º 8
0
        private void GenerateRpcServiceViewCode(
            Type type,
            CodeWriter.CodeWriter w,
            List <Tuple <MethodInfo, Tuple <string, string> > > method2PayloadTypeNames,
            Tuple <Type, List <Tuple <MethodInfo, Tuple <string, string> > > >[] typeInfos)
        {
            using (w.B($"public class {Utility.GetViewRpcServiceViewClassName(type)}{type.GetGenericParameters()} : IRpcInvokable"))
            {
                using (w.B($"public async Task<bool> Invoke(object _target_, NetDataReader _reader_, NetDataWriter _writer_)"))
                {
                    w._("NetView _view_ = _target_ as NetView;");
                    w._($"var typeEnum = ({Utility.GetInterfaceEnumName(type)})_reader_.ReadInt32();");
                    using (w.B($"switch(typeEnum)"))
                    {
                        foreach (var m in typeInfos.First().Item2)
                        {
                            var method         = m.Item1;
                            var parameters     = method.GetParameters();
                            var paramStr       = string.Join(", ", parameters.Select(p => p.GetParameterDeclaration(true)));
                            var returnType     = method.ReturnType.GenericTypeArguments.FirstOrDefault();
                            var returnTaskType = (returnType != null) ? $"Task<{returnType.GetSymbolDisplay(true)}>" : "Task";

                            w._($"case {Utility.GetInterfaceEnumName(type)}.{method.Name}:");
                            using (w.i())
                            {
                                using (w.i("{", "}"))
                                {
                                    var parameterNames = string.Join(", ", method.GetParameters().Select(p => p.Name));

                                    foreach (var param in method.GetParameters())
                                    {
                                        w._($"{Utility.GetReaderMethod(param)}");
                                    }

                                    if (returnType != null)
                                    {
                                        w._($"var _result_ = await _view_.FindRpcHandler<{type.GetSymbolDisplay()}>().{method.Name}{method.GetGenericParameters()}({parameterNames});");
                                        w._($"{Utility.GetWriteMethod(returnType, "_result_")}");
                                    }
                                    else
                                    {
                                        w._($"await _view_.FindRpcHandler<{type.GetSymbolDisplay()}>().{method.Name}{method.GetGenericParameters()}({parameterNames});");
                                    }
                                }

                                w._($"break;");
                            }
                        }

                        w._($"default: return false;");
                    }
                    w._($"return true;");
                }
            }
        }
Ejemplo n.º 9
0
        public EntryCodeGenerator(Options options)
        {
            Options = options;

            var settings = new CodeWriterSettings(CodeWriterSettings.CSharpDefault);

            settings.TranslationMapping["`"] = "\"";
            CodeWriter = new CodeWriter.CodeWriter(settings);

            GenerateHead();
        }
Ejemplo n.º 10
0
        private static void EnsureUsing(CodeWriter.CodeWriter w, string ns)
        {
            var line = $"using {ns};";

            if (w.HeadLines.Contains(line))
            {
                return;
            }

            var idx = w.HeadLines.FindLastIndex(l => l.StartsWith("using "));

            w.HeadLines.Insert(idx + 1, line);
        }
Ejemplo n.º 11
0
        public void GenerateCode(Type[] types, CodeWriter.CodeWriter w)
        {
            HashSet <string> hashSet = new HashSet <string>();

            foreach (var type in types)
            {
                var baseTypes = type.GetInterfaces().Where(t => t.FullName != "EuNet.Rpc.IRpc").ToArray();
                foreach (var t in new[] { type }.Concat(baseTypes))
                {
                    foreach (var m in t.GetMethods())
                    {
                        if (m.ReturnType.Name.StartsWith("Task") &&
                            m.ReturnType.IsGenericType)
                        {
                            Add(m.ReturnType, hashSet);
                        }

                        foreach (var p in m.GetParameters())
                        {
                            Add(p.ParameterType, hashSet);
                        }
                    }
                }
            }

            var resolverNamespace = "AOT";

            w._($"#region {resolverNamespace}");
            w._();

            using (w.B($"namespace {resolverNamespace}"))
            {
                using (w.B($"public sealed class AotCode{Options.Namespace.Replace(".","")}"))
                {
                    using (w.B("private void UsedOnlyForAOTCodeGeneration()"))
                    {
                        foreach (var code in hashSet)
                        {
                            w._(code);
                        }

                        w._("");
                        w._("throw new InvalidOperationException(\"This method is used for AOT code generation only.Do not call it at runtime.\");");
                    }
                }
            }

            w._();
            w._($"#endregion");
        }
Ejemplo n.º 12
0
        public void GenerateCode(Dictionary <string, string> formatterMap, CodeWriter.CodeWriter w)
        {
            var resolverNamespace = $"{Options.Namespace}.Resolvers".Replace(".", "");

            w._($"#region {resolverNamespace}");
            w._();

            using (w.B($"namespace {resolverNamespace}"))
            {
                GenerateResolverCode(formatterMap, w);
            }

            w._();
            w._($"#endregion");
        }
Ejemplo n.º 13
0
        private void EnsureSurrogateForIRequestTarget(Type callerType, CodeWriter.CodeWriter w)
        {
            if (_surrogateForIActorRefGenerated)
            {
                return;
            }

            var surrogateClassName = Utility.GetSurrogateClassName("IRequestTarget");

            w._($"#region {surrogateClassName}");
            w._();

            var namespaceHandle = (string.IsNullOrEmpty(callerType.Namespace) == false)
                ? w.B($"namespace {callerType.Namespace}")
                : null;

            w._("[ProtoContract]");
            using (w.B($"public class {surrogateClassName}"))
            {
                w._($"[ProtoMember(1)] public int Id;");
                w._($"[ProtoMember(2)] public string Address;");
                w._();

                w._("[ProtoConverter]");
                using (w.B($"public static {surrogateClassName} Convert(IRequestTarget value)"))
                {
                    w._($"if (value == null) return null;");
                    w._($"var target = ((BoundActorTarget)value);");
                    w._($"return new {surrogateClassName} {{ Id = target.Id, Address = target.Address }};");
                }

                w._("[ProtoConverter]");
                using (w.B($"public static IRequestTarget Convert({surrogateClassName} value)"))
                {
                    w._($"if (value == null) return null;");
                    w._($"return new BoundActorTarget(value.Id, value.Address);");
                }
            }

            namespaceHandle?.Dispose();

            w._();
            w._($"#endregion");

            _surrogateForIActorRefGenerated = true;
        }
Ejemplo n.º 14
0
        public void GenerateCode(InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w)
        {
            var iname = idecl.Identifier.ToString();

            Console.WriteLine("GenerateCode: " + iname);

            w._($"#region {iname}");
            w._();

            var namespaceScope  = idecl.GetNamespaceScope();
            var namespaceHandle = (string.IsNullOrEmpty(namespaceScope) == false)
                                      ? w.B($"namespace {idecl.GetNamespaceScope()}")
                                      : null;

            // Collect all methods and make payload type name for each one

            var methods = GetMethods(idecl);
            var method2PayloadTypeNameMap = GetPayloadTypeName(idecl, methods);

            // Collect all properties

            var snapshotProperty    = GetSnapshotProperty(idecl);
            var trackableProperties = GetTrackableProperties(idecl);

            // Generate all

            var hasServerOnlyAttribute = idecl.AttributeLists.GetAttribute("ServerOnlyAttribute") != null;

            GeneratePayloadCode(idecl, w, methods, method2PayloadTypeNameMap,
                                snapshotProperty, trackableProperties);

            GenerateServerEntityBaseCode(idecl, w, methods, method2PayloadTypeNameMap,
                                         snapshotProperty, trackableProperties);

            if (hasServerOnlyAttribute == false)
            {
                GenerateClientEntityBaseCode(idecl, w, methods, method2PayloadTypeNameMap,
                                             snapshotProperty, trackableProperties);
            }

            namespaceHandle?.Dispose();

            w._();
            w._($"#endregion");
        }
Ejemplo n.º 15
0
        public void GenerateCode(TypeDeclarationSyntax idecl, CodeWriter.CodeWriter w)
        {
            var iname = idecl.Identifier.ToString();

            Console.WriteLine("GenerateCode: " + iname);

            w._($"#region {iname}DbContext");
            w._();

            var namespaceHandle = w.B($"namespace Database");

            GenerateDbContextCode(idecl, w);

            namespaceHandle?.Dispose();

            w._();
            w._($"#endregion");
        }
Ejemplo n.º 16
0
        public void GenerateCode(Type type, CodeWriter.CodeWriter w)
        {
            Console.WriteLine("GenerateCode: " + type.GetSymbolDisplay(true));

            if (Options.UseProtobuf && Options.UseSlimClient)
            {
                EnsureSurrogateForIRequestTarget(type, w);
            }

            w._($"#region {type.GetSymbolDisplay(true)}");
            w._();

            var namespaceHandle = (string.IsNullOrEmpty(type.Namespace) == false)
                ? w.B($"namespace {type.Namespace}")
                : null;

            // Collect all methods and make payload type name for each one

            var baseTypes = type.GetInterfaces().Where(t => t.FullName != "Akka.Interfaced.IInterfacedActor").ToArray();
            var infos     = new List <Tuple <Type, List <Tuple <MethodInfo, Tuple <string, string> > > > >();

            foreach (var t in new[] { type }.Concat(baseTypes))
            {
                var methods = GetInvokableMethods(t);
                var method2PayloadTypeNameMap = GetPayloadTypeNames(t, methods);
                infos.Add(Tuple.Create(t, GetPayloadTypeNames(t, methods)));
            }

            // Generate all

            GeneratePayloadCode(type, w, infos.First().Item2);
            GenerateRefCode(type, w, baseTypes, infos.ToArray());
            if (Options.UseSlimClient == false)
            {
                GenerateSyncCode(type, w, baseTypes, infos.ToArray());
            }

            namespaceHandle?.Dispose();

            w._();
            w._($"#endregion");
        }
        private void GenerateAsyncCode(
            Type type, CodeWriter.CodeWriter w, Type[] baseTypes,
            Tuple <Type, List <Tuple <MethodInfo, string> > >[] typeInfos)
        {
            // NoReply Interface

            var baseSynces        = baseTypes.Select(t => Utility.GetObserverAsyncInterfaceName(t));
            var baseSyncesInherit = baseSynces.Any() ? string.Join(", ", baseSynces) : "IInterfacedObserverSync";

            w._($"[AlternativeInterface(typeof({type.GetSymbolDisplay(typeless: true)}))]");
            using (w.B($"public interface {Utility.GetObserverAsyncInterfaceName(type)}{type.GetGenericParameters()} : {baseSyncesInherit}{type.GetGenericConstraintClause()}"))
            {
                foreach (var m in typeInfos.First().Item2)
                {
                    var method     = m.Item1;
                    var parameters = method.GetParameters();
                    var paramStr   = string.Join(", ", parameters.Select(p => p.GetParameterDeclaration(true)));
                    w._($"Task {method.Name}{method.GetGenericParameters()}({paramStr}){method.GetGenericConstraintClause()};");
                }
            }
        }
        private void EnsureSurrogateForINotificationChannel(Type callerType, CodeWriter.CodeWriter w)
        {
            if (_surrogateForINotificationChannelGenerated)
            {
                return;
            }

            var surrogateClassName = Utility.GetSurrogateClassName("INotificationChannel");

            w._($"#region {surrogateClassName}");
            w._();

            var namespaceHandle = (string.IsNullOrEmpty(callerType.Namespace) == false)
                ? w.B($"namespace {callerType.Namespace}")
                : null;

            w._("[ProtoContract]");
            using (w.B($"public class {surrogateClassName}"))
            {
                w._("[ProtoConverter]");
                using (w.B($"public static {surrogateClassName} Convert(INotificationChannel value)"))
                {
                    w._($"if (value == null) return null;");
                    w._($"return new {surrogateClassName}();");
                }

                w._("[ProtoConverter]");
                using (w.B($"public static INotificationChannel Convert({surrogateClassName} value)"))
                {
                    w._($"return null;");
                }
            }

            namespaceHandle?.Dispose();

            w._();
            w._($"#endregion");

            _surrogateForINotificationChannelGenerated = true;
        }
Ejemplo n.º 19
0
        public void GenerateCode(InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w)
        {
            var iname = idecl.Identifier.ToString();

            Console.WriteLine("GenerateCode: " + iname);

            w._($"#region {iname}");
            w._();

            var namespaceScope  = idecl.GetNamespaceScope();
            var namespaceHandle = (string.IsNullOrEmpty(namespaceScope) == false)
                                      ? w.B($"namespace {idecl.GetNamespaceScope()}")
                                      : null;

            GenerateTrackableContainerCode(idecl, w);
            GenerateTrackableContainerTrackerCode(idecl, w);

            namespaceHandle?.Dispose();

            w._();
            w._($"#endregion");
        }
Ejemplo n.º 20
0
        public void Generate(DbRowsetDeclaration d, CodeWriter.CodeWriter w)
        {
            using (w.B($"public class {d.ClassName} : IDisposable"))
            {
                w._($"private DbDataReader _reader;");
                w._();

                using (w.B($"public {d.ClassName}(DbDataReader reader)"))
                {
                    w._($"_reader = reader;");
                }

                using (w.B($"public class Row"))
                {
                    foreach (var field in d.Fields)
                    {
                        w._($"public {DbTypeHelper.GetMemberDecl(field)};");
                    }
                }

                GenerateMethods(d, w);
            }
        }
        public void Generate(DbTableTypeDeclaration d, CodeWriter.CodeWriter w)
        {
            using (w.B($"public class {d.ClassName}"))
            {
                w._($"public DataTable Table {{ get; set; }}");
                w._();

                using (w.B($"public {d.ClassName}()"))
                {
                    w._($"Table = new DataTable();");
                    foreach (var field in d.Fields)
                    {
                        w._($"Table.Columns.Add(`{field.Name}`, typeof({field.Type}));");
                    }
                }

                var funcDecl   = string.Join(", ", d.Fields.Select(f => f.Type + " " + f.Name));
                var funcParams = string.Join(", ", d.Fields.Select(f => f.Name));
                using (w.B($"public void Add({funcDecl})"))
                {
                    w._($"Table.Rows.Add({funcParams});");
                }
            }
        }
Ejemplo n.º 22
0
        private void GenerateTrackableContainerTrackerCode(InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w)
        {
            var typeName  = idecl.GetTypeName();
            var className = "Trackable" + typeName.Substring(1) + "Tracker";

            var useProtoContract = idecl.AttributeLists.GetAttribute("ProtoContractAttribute") != null;

            if (useProtoContract)
            {
                w._($"[ProtoContract]");
            }

            using (w.B($"public class {className} : IContainerTracker<{typeName}>"))
            {
                // Property Trackers

                var properties = idecl.GetProperties();
                foreach (var p in properties)
                {
                    var protoMemberAttr = p.AttributeLists.GetAttribute("ProtoMemberAttribute");
                    if (protoMemberAttr != null)
                    {
                        w._($"[ProtoMember{protoMemberAttr.ArgumentList}] ");
                    }

                    var propertyName = p.Identifier.ToString();
                    var trackerName  = Utility.GetTrackerClassName(p.Type);
                    w._($"public {trackerName} {propertyName}Tracker {{ get; set; }} = new {trackerName}();");
                }
                w._();

                // ToString()

                using (w.B($"public override string ToString()"))
                {
                    w._("var sb = new StringBuilder();",
                        "sb.Append(\"{ \");",
                        "var first = true;");
                    foreach (var p in properties)
                    {
                        var propertyName = p.Identifier.ToString();
                        using (w.B($"if ({propertyName}Tracker != null && {propertyName}Tracker.HasChange)"))
                        {
                            w._($"if (first)",
                                $"    first = false;",
                                $"else",
                                $"    sb.Append(\", \");",
                                $"sb.Append(`{propertyName}:`);",
                                $"sb.Append({propertyName}Tracker);");
                        }
                    }
                    w._("sb.Append(\" }\");",
                        "return sb.ToString();");
                }

                // ITracker.HasChange

                using (w.B($"public bool HasChange"))
                {
                    using (w.b($"get"))
                    {
                        w._($"return");
                        foreach (var p in properties)
                        {
                            var propertyName = p.Identifier.ToString();
                            w._($"    ({propertyName}Tracker != null && {propertyName}Tracker.HasChange) ||");
                        }
                        w._($"    false;");
                    }
                }

                // ITracker.HasChange

                using (w.B($"public event TrackerHasChangeSet HasChangeSet"))
                {
                    w._("add { throw new NotImplementedException(); }",
                        "remove { throw new NotImplementedException(); }");
                }

                // ITracker.Clear

                using (w.B($"public void Clear()"))
                {
                    foreach (var p in properties)
                    {
                        var propertyName = p.Identifier.ToString();
                        w._($"if ({propertyName}Tracker != null)",
                            $"    {propertyName}Tracker.Clear();");
                    }
                }

                // ITracker.ApplyTo(Trackable)

                using (w.B($"public void ApplyTo(object trackable)"))
                {
                    w._($"ApplyTo(({typeName})trackable);");
                }

                using (w.B($"public void ApplyTo({typeName} trackable)"))
                {
                    foreach (var p in properties)
                    {
                        var propertyName = p.Identifier.ToString();
                        w._($"if ({propertyName}Tracker != null)",
                            $"    {propertyName}Tracker.ApplyTo(trackable.{propertyName});");
                    }
                }

                // ITracker.ApplyTo(Tracker)

                using (w.B($"public void ApplyTo(ITracker tracker)"))
                {
                    w._($"ApplyTo(({className})tracker);");
                }

                using (w.B($"public void ApplyTo(ITracker<{typeName}> tracker)"))
                {
                    w._($"ApplyTo(({className})tracker);");
                }

                using (w.B($"public void ApplyTo({className} tracker)"))
                {
                    foreach (var p in properties)
                    {
                        var propertyName = p.Identifier.ToString();
                        w._($"if ({propertyName}Tracker != null)",
                            $"    {propertyName}Tracker.ApplyTo(tracker.{propertyName}Tracker);");
                    }
                }

                // ITracker.RollbackTo(Trackable)

                using (w.B($"public void RollbackTo(object trackable)"))
                {
                    w._($"RollbackTo(({typeName})trackable);");
                }

                using (w.B($"public void RollbackTo({typeName} trackable)"))
                {
                    foreach (var p in properties)
                    {
                        var propertyName = p.Identifier.ToString();
                        w._($"if ({propertyName}Tracker != null)",
                            $"    {propertyName}Tracker.RollbackTo(trackable.{propertyName});");
                    }
                }

                // ITracker.RollbackTo(Tracker)

                using (w.B($"public void RollbackTo(ITracker tracker)"))
                {
                    w._($"RollbackTo(({className})tracker);");
                }

                using (w.B($"public void RollbackTo(ITracker<{typeName}> tracker)"))
                {
                    w._($"RollbackTo(({className})tracker);");
                }

                using (w.B($"public void RollbackTo({className} tracker)"))
                {
                    foreach (var p in properties)
                    {
                        var propertyName = p.Identifier.ToString();
                        w._($"if ({propertyName}Tracker != null)",
                            $"    {propertyName}Tracker.RollbackTo(tracker.{propertyName}Tracker);");
                    }
                }
            }
        }
Ejemplo n.º 23
0
        private void GenerateResolverCode(Dictionary <string, string> formatterMap, CodeWriter.CodeWriter w)
        {
            //var resolverClassName = $"{type.Namespace}Resolver".Replace(".","_");
            //var resolverHelperClassName = $"{type.Namespace}ResolverGetFormatterHelper".Replace(".", "_");
            var resolverClassName       = "GeneratedResolver";
            var resolverHelperClassName = $"{resolverClassName}GetFormatterHelper";

            using (w.B($"public sealed class {resolverClassName} : INetDataFormatterResolver"))
            {
                w._($"public static readonly {resolverClassName} Instance = new {resolverClassName}();");
                w._();

                // Constructor
                using (w.B($"private {resolverClassName}()"))
                {
                }

                // Formatter
                using (w.B("public INetDataFormatter<T> GetFormatter<T>()"))
                {
                    w._("return FormatterCache<T>.Formatter;");
                }

                // FormatterCache
                using (w.B("private static class FormatterCache<T>"))
                {
                    w._("public static readonly INetDataFormatter<T> Formatter;");
                    w._();

                    using (w.B("static FormatterCache()"))
                    {
                        w._($"Formatter = (INetDataFormatter<T>){resolverHelperClassName}.GetFormatter(typeof(T));");
                    }
                }
            }

            using (w.B($"internal static class {resolverHelperClassName}"))
            {
                using (w.i("private static readonly Dictionary<Type, object> FormatterMap = new Dictionary<Type, object>() {", "};"))
                {
                    foreach (var value in formatterMap)
                    {
                        w._($"{{ {value.Key} , {value.Value} }},");
                    }
                }

                using (w.B("internal static object GetFormatter(Type t)"))
                {
                    w._("TypeInfo ti = t.GetTypeInfo();");

                    using (w.B("if (ti.IsGenericType)"))
                    {
                        w._("Type genericType = ti.GetGenericTypeDefinition();");
                        w._("object formatterType;");

                        using (w.B("if (FormatterMap.TryGetValue(genericType, out formatterType))"))
                        {
                            w._("return Activator.CreateInstance(((Type)formatterType).MakeGenericType(ti.GenericTypeArguments));");
                        }
                    }
                    using (w.B("else"))
                    {
                        w._("object formatter;");
                        using (w.B("if (FormatterMap.TryGetValue(t, out formatter))"))
                        {
                            w._("return formatter;");
                        }
                    }

                    w._("return null;");
                }
            }
        }
Ejemplo n.º 24
0
        private void GenerateRpcCode(
            Type type, CodeWriter.CodeWriter w, Type[] baseTypes,
            Tuple <Type, List <Tuple <MethodInfo, Tuple <string, string> > > >[] typeInfos,
            Dictionary <int, string> rpcEnumMap)
        {
            // NoReply Interface

            var baseNoReplys        = baseTypes.Select(t => Utility.GetNoReplyInterfaceName(t));
            var baseNoReplysInherit = baseNoReplys.Any() ? " : " + string.Join(", ", baseNoReplys) : "";

            using (w.B($"public interface {Utility.GetNoReplyInterfaceName(type)}{type.GetGenericParameters()}{baseNoReplysInherit}{type.GetGenericConstraintClause()}"))
            {
                foreach (var m in typeInfos.First().Item2)
                {
                    var method     = m.Item1;
                    var parameters = method.GetParameters();
                    var paramStr   = string.Join(", ", parameters.Select(p => p.GetParameterDeclaration(true)));
                    w._($"void {method.Name}{method.GetGenericParameters()}({paramStr}){method.GetGenericConstraintClause()};");
                }
            }

            // Rpc Enum
            using (w.B($"public enum {Utility.GetInterfaceEnumName(type)} : int"))
            {
                foreach (var m in typeInfos.First().Item2)
                {
                    var method = m.Item1;

                    /*var parameters = method.GetParameters();
                     * var paramStr = string.Join(", ", parameters.Select(p => p.GetParameterDeclaration(true)));
                     * var returnType = method.ReturnType.GenericTypeArguments.FirstOrDefault();
                     * var returnTaskType = (returnType != null) ? $"Task<{returnType.GetSymbolDisplay(true)}>" : "Task";*/
                    var methodHash = Utility.GetMethodHashCode(Utility.GetInterfaceEnumName(type) + "." + method.Name);

                    w._($"{method.Name} = {methodHash},");

                    rpcEnumMap.Add(methodHash, $"{type.GetPureName()}.{method.Name}");
                }
            }

            // Rpc
            var rpcClassName                = Utility.GetRpcClassName(type);
            var rpcClassGenericName         = rpcClassName + type.GetGenericParameters();
            var noReplyInterfaceName        = Utility.GetNoReplyInterfaceName(type);
            var noReplyInterfaceGenericName = noReplyInterfaceName + type.GetGenericParameters();

            using (w.B($"public class {rpcClassName}{type.GetGenericParameters()} : RpcRequester, {type.GetSymbolDisplay()}, {noReplyInterfaceName}{type.GetGenericParameters()}{type.GetGenericConstraintClause()}"))
            {
                // InterfaceType property

                w._($"public override Type InterfaceType => typeof({type.GetSymbolDisplay()});");
                w._();

                // Constructors

                using (w.B($"public {rpcClassName}(NetView view, TimeSpan? timeout = null)",
                           "\t: base(NetClientGlobal.Instance.Client, new NetViewRequestWaiter(view), timeout)"))
                {
                    w._("DeliveryMethod = DeliveryMethod.Unreliable;");
                    w._("DeliveryTarget = DeliveryTarget.Others;");
                }

                using (w.B($"public {rpcClassName}(ISession target, IRequestWaiter requestWaiter, TimeSpan? timeout = null) : base(target, requestWaiter, timeout)"))
                {
                    w._("DeliveryMethod = DeliveryMethod.Unreliable;");
                    w._("DeliveryTarget = DeliveryTarget.Others;");
                }

                // With Helpers

                using (w.B($"public {rpcClassGenericName} ToTarget(DeliveryMethod deliveryMethod, ushort sessionId)"))
                {
                    w._("DeliveryMethod = deliveryMethod;");
                    w._("DeliveryTarget = DeliveryTarget.Target;");
                    w._("Extra = sessionId;");
                    w._("return this;");
                }

                using (w.B($"public {rpcClassGenericName} ToMaster(DeliveryMethod deliveryMethod)"))
                {
                    w._("DeliveryMethod = deliveryMethod;");
                    w._("DeliveryTarget = DeliveryTarget.Master;");
                    w._("return this;");
                }

                using (w.B($"public {noReplyInterfaceGenericName} ToOthers(DeliveryMethod deliveryMethod)"))
                {
                    w._("DeliveryMethod = deliveryMethod;");
                    w._("DeliveryTarget = DeliveryTarget.Others;");
                    w._("return this;");
                }

                using (w.B($"public {noReplyInterfaceGenericName} ToAll(DeliveryMethod deliveryMethod)"))
                {
                    w._("DeliveryMethod = deliveryMethod;");
                    w._("DeliveryTarget = DeliveryTarget.All;");
                    w._("return this;");
                }

                using (w.B($"public {noReplyInterfaceGenericName} WithNoReply()"))
                {
                    w._("return this;");
                }

                using (w.B($"public {rpcClassGenericName} WithRequestWaiter(IRequestWaiter requestWaiter)"))
                {
                    w._($"return new {rpcClassGenericName}(Target, requestWaiter, Timeout);");
                }

                using (w.B($"public {rpcClassGenericName} WithTimeout(TimeSpan? timeout)"))
                {
                    w._($"return new {rpcClassGenericName}(Target, RequestWaiter, timeout);");
                }

                // IInterface message methods

                foreach (var t in typeInfos)
                {
                    var payloadTableClassName = Utility.GetRpcServiceClassName(t.Item1) + type.GetGenericParameters();

                    foreach (var m in t.Item2)
                    {
                        var method       = m.Item1;
                        var payloadTypes = m.Item2;
                        var parameters   = method.GetParameters();

                        var parameterTypeNames = string.Join(", ", parameters.Select(p => p.GetParameterDeclaration(true)));
                        var parameterInits     = string.Join(", ", parameters.Select(Utility.GetParameterAssignment));
                        var returnType         = method.ReturnType.GenericTypeArguments.FirstOrDefault();

                        // Request Methods

                        var returnTaskType = (returnType != null) ? $"Task<{returnType.GetSymbolDisplay(true)}>" : "Task";
                        var prototype      = $"public async {returnTaskType} {method.Name}{method.GetGenericParameters()}({parameterTypeNames}){method.GetGenericConstraintClause()}";
                        using (w.B(prototype))
                        {
                            w._("var _writer_ = NetPool.DataWriterPool.Alloc();");
                            w._("try");
                            using (w.i("{", "}"))
                            {
                                w._($"_writer_.Write((int){Utility.GetInterfaceEnumName(type)}.{method.Name});");

                                foreach (var param in parameters)
                                {
                                    w._($"{Utility.GetWriteMethod(param)}");
                                }

                                if (returnType != null)
                                {
                                    using (w.B($"using(var _reader_ = await SendRequestAndReceive(_writer_))"))
                                    {
                                        w._($"return {Utility.GetReaderMethod(returnType)}");
                                    }
                                }
                                else
                                {
                                    w._($"await SendRequestAndWait(_writer_);");
                                }
                            }
                            w._("finally");
                            using (w.i("{", "}"))
                            {
                                w._($"NetPool.DataWriterPool.Free(_writer_);");
                            }
                        }
                    }
                }

                // IInterface_NoReply message methods

                foreach (var t in typeInfos)
                {
                    var interfaceName        = Utility.GetNoReplyInterfaceName(t.Item1);
                    var interfaceGenericName = interfaceName + t.Item1.GetGenericParameters();

                    var payloadTableClassName = Utility.GetRpcServiceClassName(t.Item1) + type.GetGenericParameters();

                    foreach (var m in t.Item2)
                    {
                        var method       = m.Item1;
                        var payloadTypes = m.Item2;
                        var parameters   = method.GetParameters();

                        var parameterTypeNames = string.Join(", ", parameters.Select(p => p.GetParameterDeclaration(false)));
                        var parameterInits     = string.Join(", ", parameters.Select(Utility.GetParameterAssignment));

                        // Request Methods

                        using (w.B($"void {interfaceGenericName}.{method.Name}{method.GetGenericParameters()}({parameterTypeNames})"))
                        {
                            w._("var _writer_ = NetPool.DataWriterPool.Alloc();");
                            w._("try");
                            using (w.i("{", "}"))
                            {
                                w._($"_writer_.Write((int){Utility.GetInterfaceEnumName(type)}.{method.Name});");

                                foreach (var param in parameters)
                                {
                                    w._($"{Utility.GetWriteMethod(param)}");
                                }

                                w._("SendRequest(_writer_);");
                            }
                            w._("finally");
                            using (w.i("{", "}"))
                            {
                                w._($"NetPool.DataWriterPool.Free(_writer_);");
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 25
0
        private void GeneratePayloadCode(
            InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w,
            MethodDeclarationSyntax[] methods, Dictionary <MethodDeclarationSyntax, string> method2PayloadTypeNameMap,
            PropertyDeclarationSyntax snapshotProperty, PropertyDeclarationSyntax[] trackableProperties)
        {
            var className = Utility.GetPayloadTableClassName(idecl);

            w._($"[PayloadTableForEntity(typeof({idecl.Identifier}))]");
            using (w.B($"public static class {className}"))
            {
                // generate GetPayloadTypes method

                using (w.B("public static Type[] GetPayloadTypes()"))
                {
                    using (w.I("return new Type[] {", "};"))
                    {
                        foreach (var method in methods)
                        {
                            w._($"typeof({method2PayloadTypeNameMap[method]}),");
                        }
                    }
                }

                // generate payload classes for all methods

                foreach (var method in methods)
                {
                    var payloadTypeName = method2PayloadTypeNameMap[method];

                    if (Options.UseProtobuf)
                    {
                        w._("[ProtoContract, TypeAlias]");
                    }

                    using (w.B($"public class {payloadTypeName} : IInvokePayload"))
                    {
                        // Parameters

                        var parameters = method.ParameterList.Parameters;
                        for (var i = 0; i < parameters.Count; i++)
                        {
                            var parameter = parameters[i];

                            var attr = "";
                            var defaultValueExpression = "";

                            if (Options.UseProtobuf)
                            {
                                var defaultValueAttr =
                                    parameter.Default != null
                                        ? $", DefaultValue({parameter.Default.Value})"
                                        : "";
                                attr = $"[ProtoMember({i + 1}){defaultValueAttr}] ";

                                if (parameter.Default != null)
                                {
                                    defaultValueExpression = " " + parameter.Default;
                                }
                            }

                            var typeName = parameter.Type;
                            w._($"{attr}public {typeName} {parameter.Identifier}{defaultValueExpression};");
                        }

                        if (parameters.Any())
                        {
                            w._();
                        }

                        // Flags

                        var hasPassThroughAttribute   = method.AttributeLists.GetAttribute("PassThroughAttribute") != null;
                        var hasToClientAttribute      = method.AttributeLists.GetAttribute("ToClientAttribute") != null;
                        var hasToServerAttribute      = method.AttributeLists.GetAttribute("ToServerAttribute") != null;
                        var hasAnyoneCanCallAttribute = method.AttributeLists.GetAttribute("AnyoneCanCallAttribute") != null;

                        var flags = new List <string>();
                        if (hasPassThroughAttribute)
                        {
                            flags.Add("PayloadFlags.PassThrough");
                        }
                        if (hasToClientAttribute)
                        {
                            flags.Add("PayloadFlags.ToServer");
                        }
                        if (hasToServerAttribute)
                        {
                            flags.Add("PayloadFlags.ToClient");
                        }
                        if (hasAnyoneCanCallAttribute)
                        {
                            flags.Add("PayloadFlags.AnyoneCanCall");
                        }
                        if (flags.Count == 0)
                        {
                            flags.Add("0");
                        }
                        w._($"public PayloadFlags Flags {{ get {{ return {string.Join(" | ", flags)}; }} }}");
                        w._();

                        // GetInterfaceType

                        var excludeServer     = hasToClientAttribute || hasPassThroughAttribute;
                        var excludeClient     = hasToServerAttribute;
                        var interfaceBodyName = idecl.Identifier.ToString().Substring(1);

                        /*
                         * w._($"public Type GetInterfaceType() {{ return typeof({idecl.Identifier}); }}");
                         * if (excludeServer)
                         *  w._($"public Type GetServerInterfaceType() {{ return null; }}");
                         * else
                         *  w._($"public Type GetServerInterfaceType() {{ return typeof(IServer{interfaceBodyName}); }}");
                         * if (excludeClient)
                         *  w._($"public Type GetClientInterfaceType() {{ return null; }}");
                         * else
                         *  w._($"public Type GetClientInterfaceType() {{ return typeof(IClient{interfaceBodyName}); }}");
                         * sb.AppendLine();
                         */

                        // Invoke

                        var parameterNames = string.Join(", ", parameters.Select(p => p.Identifier));

                        using (w.B("public void InvokeServer(IEntityServerHandler target)"))
                        {
                            if (excludeServer == false)
                            {
                                w._($"((I{interfaceBodyName}ServerHandler)target).On{method.Identifier}({parameterNames});");
                            }
                        }

                        using (w.B("public void InvokeClient(IEntityClientHandler target)"))
                        {
                            if (excludeClient == false)
                            {
                                w._($"((I{interfaceBodyName}ClientHandler)target).On{method.Identifier}({parameterNames});");
                            }
                        }
                    }
                }

                // generate a payload class for spawn

                if (snapshotProperty != null || (trackableProperties != null && trackableProperties.Length > 0))
                {
                    GeneratePayloadCodeForSpawn(idecl, w, snapshotProperty, trackableProperties);
                }

                // generate a payload class for update-change

                if (trackableProperties != null && trackableProperties.Length > 0)
                {
                    GeneratePayloadCodeForUpdateChange(idecl, w, trackableProperties);
                }
            }
        }
Ejemplo n.º 26
0
        private void GenerateClientEntityBaseCode(
            InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w,
            MethodDeclarationSyntax[] methods, Dictionary <MethodDeclarationSyntax, string> method2PayloadTypeNameMap,
            PropertyDeclarationSyntax snapshotProperty, PropertyDeclarationSyntax[] trackableProperties)
        {
            var payloadTableClassName = Utility.GetPayloadTableClassName(idecl);

            var sb            = new StringBuilder();
            var interfaceName = "I" + idecl.Identifier.ToString().Substring(1) + "ClientHandler";
            var baseClassName = Utility.GetClientEntityBaseClassName(idecl);

            // IEntityClientHandler

            var interfaceMethods = methods.Where(
                m => m.AttributeLists.GetAttribute("ToServerAttribute") == null).ToArray();

            using (w.B($"public interface {interfaceName} : IEntityClientHandler"))
            {
                foreach (var method in interfaceMethods)
                {
                    w._($"{method.ReturnType} On{method.Identifier}{method.ParameterList};");
                }
            }

            // ClientEntityBase class

            using (w.B($"public abstract class {baseClassName} : {Options.ClientEntity ?? "ClientEntity"}"))
            {
                if (trackableProperties.Length > 0)
                {
                    foreach (var property in trackableProperties)
                    {
                        w._($"public Trackable{property.Type.ToString().Substring(1)} {property.Identifier} {{ get; set; }}");
                    }

                    w._();

                    using (w.B($"protected {baseClassName}()"))
                    {
                        foreach (var property in trackableProperties)
                        {
                            w._($"{property.Identifier} = new Trackable{property.Type.ToString().Substring(1)}();");
                        }
                    }
                }

                if (snapshotProperty != null)
                {
                    w._($"public override object Snapshot {{ set {{ OnSnapshot(({snapshotProperty.Type})value); }} }}");
                    w._();
                    w._($"public abstract void OnSnapshot({snapshotProperty.Type} snapshot);");
                    w._();
                }

                w._($"public override int TrackableDataCount {{ get {{ return {trackableProperties.Length}; }} }}");
                w._();

                using (w.B("public override ITrackable GetTrackableData(int index)"))
                {
                    for (int i = 0; i < trackableProperties.Length; i++)
                    {
                        w._($"if (index == {i}) return {trackableProperties[i].Identifier};");
                    }
                    w._("return null;");
                }

                using (w.B("public override void SetTrackableData(int index, ITrackable trackable)"))
                {
                    for (int i = 0; i < trackableProperties.Length; i++)
                    {
                        w._($"if (index == {i}) {trackableProperties[i].Identifier} = " +
                            $"(Trackable{trackableProperties[i].Type.ToString().Substring(1)})trackable;");
                    }
                }

                var classMethods = methods.Where(
                    m => m.AttributeLists.GetAttribute("ToClientAttribute") == null).ToArray();

                foreach (var method in classMethods)
                {
                    var messageName = method2PayloadTypeNameMap[method];
                    var parameters  = method.ParameterList.Parameters;

                    var parameterTypeNames = string.Join(", ", parameters.Select(p => p.ToString()));
                    var parameterInits     = string.Join(", ", parameters.Select(p => p.Identifier + " = " + p.Identifier));

                    using (w.B($"public void {method.Identifier}({parameterTypeNames})"))
                    {
                        w._($"var payload = new {payloadTableClassName}.{messageName} {{ {parameterInits} }};",
                            $"SendInvoke(payload);");
                    }
                }
            }
        }
Ejemplo n.º 27
0
        private void GeneratePayloadCodeForUpdateChange(
            InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w,
            PropertyDeclarationSyntax[] trackableProperties)
        {
            if (Options.UseProtobuf)
            {
                w._("[ProtoContract, TypeAlias]");
            }

            using (w.B("public class UpdateChange : IUpdateChangePayload"))
            {
                // Members

                var protobufMemberIndex = 0;
                foreach (var p in trackableProperties)
                {
                    var attr = "";
                    if (Options.UseProtobuf)
                    {
                        protobufMemberIndex += 1;
                        attr = $"[ProtoMember({protobufMemberIndex})] ";
                    }

                    w._($"{attr}public {Utility.GetTrackerClassName(p.Type)} {p.Identifier}Tracker;");
                }

                w._();

                // Gather

                using (w.B("public void Gather(IServerEntity entity)"))
                {
                    w._($"var e = ({Utility.GetServerEntityBaseClassName(idecl)})entity;");

                    foreach (var p in trackableProperties)
                    {
                        using (w.b($"if (e.{p.Identifier}.Changed)"))
                        {
                            w._($"{p.Identifier}Tracker = ({Utility.GetTrackerClassName(p.Type)})e.{p.Identifier}.Tracker;");
                        }
                    }
                }

                // Notify

                using (w.B("public void Notify(IClientEntity entity)"))
                {
                    w._($"var e = ({Utility.GetClientEntityBaseClassName(idecl)})entity;");

                    for (int i = 0; i < trackableProperties.Length; i++)
                    {
                        var p = trackableProperties[i];
                        using (w.b($"if ({p.Identifier}Tracker != null)"))
                        {
                            w._($"e.OnTrackableDataChanging({i}, {p.Identifier}Tracker);");
                            w._($"{p.Identifier}Tracker.ApplyTo(e.{p.Identifier});");
                            w._($"e.OnTrackableDataChanged({i}, {p.Identifier}Tracker);");
                        }
                    }
                }
            }
        }
Ejemplo n.º 28
0
        private void GeneratePayloadCodeForSpawn(
            InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w,
            PropertyDeclarationSyntax snapshotProperty, PropertyDeclarationSyntax[] trackableProperties)
        {
            if (Options.UseProtobuf)
            {
                w._("[ProtoContract, TypeAlias]");
            }

            using (w.B("public class Spawn : ISpawnPayload"))
            {
                // Members

                var protobufMemberIndex = 0;

                if (trackableProperties != null)
                {
                    foreach (var p in trackableProperties)
                    {
                        var attr = "";
                        if (Options.UseProtobuf)
                        {
                            protobufMemberIndex += 1;
                            attr = $"[ProtoMember({protobufMemberIndex})] ";
                        }

                        w._($"{attr}public Trackable{p.Type.ToString().Substring(1)} {p.Identifier};");
                    }
                }

                if (snapshotProperty != null)
                {
                    var attr = "";
                    if (Options.UseProtobuf)
                    {
                        protobufMemberIndex += 1;
                        attr = $"[ProtoMember({protobufMemberIndex})] ";
                    }

                    w._($"{attr}public {snapshotProperty.Type} {snapshotProperty.Identifier};");
                }

                w._();

                // Notify

                using (w.B("public void Gather(IServerEntity entity)"))
                {
                    w._($"var e = ({Utility.GetServerEntityBaseClassName(idecl)})entity;");

                    if (trackableProperties != null)
                    {
                        foreach (var p in trackableProperties)
                        {
                            w._($"{p.Identifier} = e.{p.Identifier};");
                        }
                    }

                    if (snapshotProperty != null)
                    {
                        w._($"{snapshotProperty.Identifier} = e.OnSnapshot();");
                    }
                }

                // Gather

                using (w.B("public void Notify(IClientEntity entity)"))
                {
                    w._($"var e = ({Utility.GetClientEntityBaseClassName(idecl)})entity;");

                    if (trackableProperties != null)
                    {
                        foreach (var p in trackableProperties)
                        {
                            w._($"e.{p.Identifier} = {p.Identifier};");
                        }
                    }

                    if (snapshotProperty != null)
                    {
                        w._($"e.OnSnapshot({snapshotProperty.Identifier});");
                    }
                }
            }
        }
Ejemplo n.º 29
0
        private static int Process(Options options)
        {
            try
            {
                Console.WriteLine("Start Process!");

                // Resolve options

                var basePath = Path.GetFullPath(options.Path ?? ".");
                var sources =
                    options.Sources.Where(p => string.IsNullOrWhiteSpace(p) == false &&
                                               p.ToLower().IndexOf(".codegen.cs") == -1)
                           .Select(p => MakeFullPath(p, basePath))
                           .ToArray();
                var references =
                    options.References.Where(p => string.IsNullOrWhiteSpace(p) == false)
                           .Select(p => MakeFullPath(p, basePath))
                           .ToArray();
                var targetDefaultPath = @".\Properties\TrackableData.CodeGen.cs";
                var targetPath = MakeFullPath(options.TargetFile ?? targetDefaultPath, basePath);

                // Parse sources and extract interfaces

                Console.WriteLine("- Parse sources");

                var syntaxTrees = sources.Select(
                    file => CSharpSyntaxTree.ParseText(File.ReadAllText(file), path: file)).ToArray();
                var interfaceDeclarations = syntaxTrees.SelectMany(
                    st => st.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>()).ToArray();

                // Generate code

                Console.WriteLine("- Generate code");

                var settings = new CodeWriterSettings(CodeWriterSettings.CSharpDefault);
                settings.TranslationMapping["`"] = "\"";

                var w = new CodeWriter.CodeWriter(settings);
                var relatedSourceTrees = new HashSet<SyntaxNode>();

                w.HeadLines = new List<string>
                {
                    "// ------------------------------------------------------------------------------",
                    "// <auto-generated>",
                    "//     This code was generated by TrackableData.CodeGenerator.",
                    "//",
                    "//     Changes to this file may cause incorrect behavior and will be lost if",
                    "//     the code is regenerated.",
                    "// </auto-generated>",
                    "// ------------------------------------------------------------------------------",
                    "",
                    "using System;",
                    "using System.Collections.Generic;",
                    "using System.Reflection;",
                    "using System.Runtime.Serialization;",
                    "using System.Linq;",
                    "using System.Text;",
                    "using TrackableData;",
                    ""
                };

                // TrackablePoco

                var pocoCodeGen = new TrackablePocoCodeGenerator() { Options = options };
                foreach (var idecl in interfaceDeclarations)
                {
                    var baseType = idecl.GetGenericBase("TrackableData.ITrackablePoco");
                    if (baseType != null)
                    {
                        var pocoType = baseType.TypeArgumentList.Arguments[0].ToString();
                        if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), pocoType) == false)
                        {
                            throw new Exception($"Invalid base type of ITrackablePoco<{pocoType}>");
                        }

                        pocoCodeGen.GenerateCode(idecl, w);
                        relatedSourceTrees.Add(idecl.GetRootNode());
                    }
                }

                // TrackableContainer

                var containerCodeGen = new TrackableContainerCodeGenerator() { Options = options };
                foreach (var idecl in interfaceDeclarations)
                {
                    var baseType = idecl.GetGenericBase("TrackableData.ITrackableContainer");
                    if (baseType != null)
                    {
                        var containerType = baseType.TypeArgumentList.Arguments[0].ToString();
                        if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), containerType) == false)
                        {
                            throw new Exception($"Invalid base type of ITrackableContainer<{containerType}>");
                        }

                        containerCodeGen.GenerateCode(idecl, w);
                        relatedSourceTrees.Add(idecl.GetRootNode());
                    }
                }

                // Resolve referenced using

                var usingDirectives = new HashSet<string>(relatedSourceTrees.SelectMany(
                    st => st.DescendantNodes().OfType<UsingDirectiveSyntax>()).Select(x => x.Name.ToString()));
                foreach (var usingDirective in usingDirectives)
                    EnsureUsing(w, usingDirective);

                // Save generated code

                Console.WriteLine("- Save code");

                if (w.WriteAllText(targetPath, true) == false)
                    Console.WriteLine("Nothing changed. Skip writing.");

                return 0;
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception in processing:\n" + e);
                return 1;
            }
        }
        private void GenerateTrackablePocoSurrogateCode(InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w)
        {
            var sb                 = new StringBuilder();
            var typeName           = idecl.GetTypeName();
            var trackableClassName = "Trackable" + typeName.Substring(1);
            var className          = trackableClassName + "TrackerSurrogate";

            w._($"[ProtoContract]");
            using (w.B($"public class {className}"))
            {
                // Collect properties with ProtoMemberAttribute attribute

                var propertyWithTags =
                    idecl.GetProperties()
                    .Select(p => Tuple.Create(p, p.AttributeLists.GetAttribute("ProtoMemberAttribute")))
                    .Where(x => x.Item2 != null)
                    .ToArray();

                // ProtoMember

                foreach (var item in propertyWithTags)
                {
                    var p = item.Item1;
                    w._($"[ProtoMember{item.Item2.ArgumentList}] " +
                        $"public EnvelopedObject<{p.Type}> {p.Identifier};");
                }
                w._();

                // ConvertTrackerToSurrogate

                w._("[ProtoConverter]");
                using (w.B($"public static {className} Convert(TrackablePocoTracker<{typeName}> tracker)"))
                {
                    w._($"if (tracker == null)",
                        $"    return null;");
                    w._();

                    w._($"var surrogate = new {className}();");
                    using (w.B($"foreach(var changeItem in tracker.ChangeMap)"))
                    {
                        using (w.B($"switch (changeItem.Key.Name)"))
                        {
                            foreach (var item in propertyWithTags)
                            {
                                var p = item.Item1;

                                w._($"case \"{item.Item1.Identifier}\":");
                                w._($"    surrogate.{p.Identifier} = new EnvelopedObject<{p.Type}>" +
                                    $" {{ Value = ({p.Type})changeItem.Value.NewValue }};");
                                w._($"    break;");
                            }
                        }
                    }
                    w._($"return surrogate;");
                }

                // ConvertSurrogateToTracker

                w._("[ProtoConverter]");
                using (w.B($"public static TrackablePocoTracker<{typeName}> Convert({className} surrogate)"))
                {
                    w._($"if (surrogate == null)",
                        $"    return null;");
                    w._();
                    w._($"var tracker = new TrackablePocoTracker<{typeName}>();");
                    foreach (var item in propertyWithTags)
                    {
                        var p = item.Item1;

                        w._($"if (surrogate.{p.Identifier} != null)");
                        w._($"    tracker.ChangeMap.Add({trackableClassName}.PropertyTable.{p.Identifier}, " +
                            $"new TrackablePocoTracker<{typeName}>.Change {{ NewValue = surrogate.{p.Identifier}.Value }});");
                    }
                    w._($"return tracker;");
                }
            }
        }
        private void GenerateTrackablePocoCode(InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w,
                                               bool useProtoContract)
        {
            var typeName  = idecl.GetTypeName();
            var className = "Trackable" + typeName.Substring(1);

            var properties          = idecl.GetProperties();
            var trackableProperties = Utility.GetTrackableProperties(properties);

            if (useProtoContract)
            {
                w._($"[ProtoContract]");
            }

            using (w.B($"public partial class {className} : {typeName}"))
            {
                // Tracker

                w._($"[IgnoreDataMember]",
                    $"public IPocoTracker<{typeName}> Tracker {{ get; set; }}");
                w._();

                // Clone

                using (w.B($"public {className} Clone()"))
                {
                    w._($"var o = new {className}();");
                    foreach (var p in properties)
                    {
                        if (Utility.IsTrackableType(p.Type))
                        {
                            w._($"o._{p.Identifier} = _{p.Identifier}?.Clone();");
                        }
                        else
                        {
                            w._($"o._{p.Identifier} = _{p.Identifier};");
                        }
                    }
                    w._($"return o;");
                }

                // ITrackable.Changed

                w._("[IgnoreDataMember]",
                    "public bool Changed { get { return Tracker != null && Tracker.HasChange; } }");
                w._();

                // ITrackable.Tracker

                using (w.B($"ITracker ITrackable.Tracker"))
                {
                    using (w.b($"get"))
                    {
                        w._($"return Tracker;");
                    }
                    using (w.b($"set"))
                    {
                        w._($"var t = (IPocoTracker<{typeName}>)value;",
                            $"Tracker = t;");
                    }
                }

                // ITrackable<T>.Tracker

                using (w.B($"ITracker<{typeName}> ITrackable<{typeName}>.Tracker"))
                {
                    using (w.b($"get"))
                    {
                        w._($"return Tracker;");
                    }
                    using (w.b($"set"))
                    {
                        w._($"var t = (IPocoTracker<{typeName}>)value;",
                            $"Tracker = t;");
                    }
                }

                // ITrackable.Clone

                using (w.B($"ITrackable ITrackable.Clone()"))
                {
                    w._($"return Clone();");
                }

                // ITrackable.GetChildTrackable

                using (w.B($"public ITrackable GetChildTrackable(object name)"))
                {
                    using (w.B($"switch ((string)name)"))
                    {
                        foreach (var p in trackableProperties)
                        {
                            w._($"case \"{p.Identifier}\":",
                                $"    return {p.Identifier} as ITrackable;");
                        }
                        w._($"default:",
                            $"    return null;");
                    }
                }

                // ITrackable.GetChildTrackables

                using (w.B($"public IEnumerable<KeyValuePair<object, ITrackable>> " + $"" +
                           $"GetChildTrackables(bool changedOnly = false)"))
                {
                    if (trackableProperties.Any())
                    {
                        foreach (var p in trackableProperties)
                        {
                            var id = p.Identifier;
                            w._($"var trackable{id} = {id} as ITrackable;",
                                $"if (trackable{id} != null && (changedOnly == false || trackable{id}.Changed))",
                                $"    yield return new KeyValuePair<object, ITrackable>(`{id}`, trackable{id});");
                        }
                    }
                    else
                    {
                        w._($"yield break;");
                    }
                }

                // Property Table

                using (w.B($"public static class PropertyTable"))
                {
                    foreach (var p in properties)
                    {
                        w._($"public static readonly PropertyInfo {p.Identifier} = " +
                            $"typeof({typeName}).GetProperty(\"{p.Identifier}\");");
                    }
                }

                // Property Accessors

                foreach (var p in properties)
                {
                    var propertyType = p.Type.ToString();
                    var propertyName = p.Identifier.ToString();

                    w._();
                    w._($"private {propertyType} _{p.Identifier};");
                    w._();

                    var protoMemberAttr = p.AttributeLists.GetAttribute("ProtoMemberAttribute");
                    if (protoMemberAttr != null)
                    {
                        w._($"[ProtoMember{protoMemberAttr?.ArgumentList}] ");
                    }

                    using (w.B($"public {propertyType} {propertyName}"))
                    {
                        using (w.b($"get"))
                        {
                            w._($"return _{propertyName};");
                        }
                        using (w.b($"set"))
                        {
                            var compare = $"{propertyName} != value";

                            // Because DateTime ignores Kind for checking equal, compare it additionally.
                            if (CodeAnalaysisExtensions.CompareTypeName(propertyType, "System.DateTime"))
                            {
                                compare = $"({propertyName} != value || {propertyName}.Kind != value.Kind)";
                            }
                            if (CodeAnalaysisExtensions.CompareTypeName(propertyType, "System.DateTime?"))
                            {
                                compare = $"({propertyName} != value || ({propertyName}.HasValue && {propertyName}.Value.Kind != value.Value.Kind))";
                            }

                            w._($"if (Tracker != null && {compare})",
                                $"    Tracker.TrackSet(PropertyTable.{propertyName}, _{propertyName}, value);",
                                $"_{propertyName} = value;");
                        }
                    }
                }
            }
        }
Ejemplo n.º 32
0
        private void GenerateTrackableContainerCode(InterfaceDeclarationSyntax idecl, CodeWriter.CodeWriter w)
        {
            var typeName  = idecl.GetTypeName();
            var className = "Trackable" + typeName.Substring(1);

            var useProtoContract = idecl.AttributeLists.GetAttribute("ProtoContractAttribute") != null;

            if (useProtoContract)
            {
                w._($"[ProtoContract]");
            }

            using (w.B($"public partial class {className} : {typeName}"))
            {
                var properties = idecl.GetProperties();

                // Tracker

                w._($"[IgnoreDataMember]",
                    $"private {className}Tracker _tracker;");
                w._();

                w._($"[IgnoreDataMember]");
                using (w.B($"public {className}Tracker Tracker"))
                {
                    using (w.b($"get"))
                    {
                        w._($"return _tracker;");
                    }
                    using (w.b($"set"))
                    {
                        w._($"_tracker = value;");
                        foreach (var p in properties)
                        {
                            var propertyName = p.Identifier.ToString();
                            w._($"{propertyName}.Tracker = value?.{propertyName}Tracker;");
                        }
                    }
                }

                // Clone

                using (w.B($"public {className} Clone()"))
                {
                    w._($"var o = new {className}();");
                    foreach (var p in properties)
                    {
                        w._($"o._{p.Identifier} = _{p.Identifier}?.Clone();");
                    }
                    w._($"return o;");
                }

                // ITrackable.Changed

                w._("public bool Changed { get { return Tracker != null && Tracker.HasChange; } }");
                w._();

                // ITrackable.Tracker

                using (w.B($"ITracker ITrackable.Tracker"))
                {
                    using (w.b($"get"))
                    {
                        w._($"return Tracker;");
                    }
                    using (w.b($"set"))
                    {
                        w._($"var t = ({className}Tracker)value;");
                        w._($"Tracker = t;");
                    }
                }

                // ITrackable<T>.Tracker

                using (w.B($"ITracker<{typeName}> ITrackable<{typeName}>.Tracker"))
                {
                    using (w.b($"get"))
                    {
                        w._($"return Tracker;");
                    }
                    using (w.b($"set"))
                    {
                        w._($"var t = ({className}Tracker)value;");
                        w._($"Tracker = t;");
                    }
                }

                // IContainerTracker<T>.Tracker

                using (w.B($"IContainerTracker<{typeName}> ITrackableContainer<{typeName}>.Tracker"))
                {
                    using (w.b($"get"))
                    {
                        w._($"return Tracker;");
                    }
                    using (w.b($"set"))
                    {
                        w._($"var t = ({className}Tracker)value;");
                        w._($"Tracker = t;");
                    }
                }

                // ITrackable.Clone

                using (w.B($"ITrackable ITrackable.Clone()"))
                {
                    w._($"return Clone();");
                }

                // ITrackable.GetChildTrackable

                using (w.B($"public ITrackable GetChildTrackable(object name)"))
                {
                    using (w.b($"switch ((string)name)"))
                    {
                        foreach (var p in properties)
                        {
                            var propertyName = p.Identifier.ToString();
                            w._($"case \"{propertyName}\":",
                                $"    return {propertyName} as ITrackable;");
                        }
                        w._($"default:",
                            $"    return null;");
                    }
                }

                // ITrackable.GetChildTrackables

                using (w.B($"public IEnumerable<KeyValuePair<object, ITrackable>> " +
                           $"GetChildTrackables(bool changedOnly = false)"))
                {
                    if (properties.Any())
                    {
                        foreach (var p in properties)
                        {
                            var propertyType = p.Type.ToString();
                            var propertyName = p.Identifier.ToString();
                            w._($"var trackable{propertyName} = {propertyName} as ITrackable;",
                                $"if (trackable{propertyName} != null && (changedOnly == false || trackable{propertyName}.Changed))",
                                $"    yield return new KeyValuePair<object, ITrackable>(\"{propertyName}\", trackable{propertyName});");
                        }
                    }
                    else
                    {
                        w._($"yield break;");
                    }
                }

                // Property Accessors

                foreach (var p in properties)
                {
                    var propertyType = p.Type.ToString();
                    var propertyName = p.Identifier.ToString();

                    w._();
                    w._($"private {propertyType} _{propertyName} = new {propertyType}();");
                    w._();

                    var protoMemberAttr = p.AttributeLists.GetAttribute("ProtoMemberAttribute");
                    if (protoMemberAttr != null)
                    {
                        w._($"[ProtoMember{protoMemberAttr.ArgumentList}] ");
                    }

                    using (w.B($"public {propertyType} {propertyName}"))
                    {
                        using (w.b($"get"))
                        {
                            w._($"return _{propertyName};");
                        }
                        using (w.b($"set"))
                        {
                            w._($"if (_{propertyName} != null)",
                                $"    _{propertyName}.Tracker = null;",
                                $"if (value != null)",
                                $"    value.Tracker = Tracker?.{propertyName}Tracker;",
                                $"_{propertyName} = value;");
                        }
                    }

                    using (w.B($"{propertyType} {typeName}.{propertyName}"))
                    {
                        w._($"get {{ return _{propertyName}; }}",
                            $"set {{ _{propertyName} = ({propertyType})value; }}");
                    }
                }
            }
        }