コード例 #1
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(";");
                }
            }
        }
コード例 #2
0
        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;");
                        }
                    }
                }
            }
        }
コード例 #3
0
        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;");
                }
            }
        }
コード例 #4
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; }}");
                    }
                }
            }
        }
コード例 #5
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);");
                    }
                }
            }
        }
コード例 #6
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; }}");
                    }
                }
            }
        }
コード例 #7
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);");
                    }
                }
            }
        }
コード例 #8
0
        private void GenerateTrackablePocoCode(InterfaceDeclarationSyntax idecl, ICodeGenWriter writer, bool useProtoContract)
        {
            var sb = new StringBuilder();
            var typeName = idecl.GetTypeName();
            var className = "Trackable" + typeName.Substring(1);

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

            if (useProtoContract)
                sb.AppendLine("[ProtoContract]");
            sb.AppendLine($"public partial class {className} : {typeName}");
            sb.AppendLine("{");

            // Tracker

            sb.AppendLine("\t[IgnoreDataMember]");
            sb.AppendFormat("\tpublic IPocoTracker<{0}> Tracker {{ get; set; }}\n", typeName);
            sb.AppendLine("");

            // ITrackable.Changed

            sb.AppendLine("\tpublic bool Changed { get { return Tracker != null && Tracker.HasChange; } }");
            sb.AppendLine("");

            // ITrackable.Tracker

            sb.AppendLine("\tITracker ITrackable.Tracker");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tget");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\treturn Tracker;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t\tset");
            sb.AppendLine("\t\t{");
            sb.AppendFormat("\t\t\tvar t = (IPocoTracker<{0}>)value;\n", typeName);
            sb.AppendLine("\t\t\tTracker = t;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t}");
            sb.AppendLine("");

            // ITrackable<T>.Tracker

            sb.AppendLine($"\tITracker<{typeName}> ITrackable<{typeName}>.Tracker");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tget");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\treturn Tracker;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t\tset");
            sb.AppendLine("\t\t{");
            sb.AppendFormat("\t\t\tvar t = (IPocoTracker<{0}>)value;\n", typeName);
            sb.AppendLine("\t\t\tTracker = t;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t}");
            sb.AppendLine("");

            // ITrackable.GetChildTrackable

            sb.AppendLine("\tpublic ITrackable GetChildTrackable(object name)");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tswitch ((string)name)");
            sb.AppendLine("\t\t{");
            foreach (var p in trackableProperties)
            {
                sb.AppendLine($"\t\t\tcase \"{p.Identifier}\":");
                sb.AppendLine($"\t\t\t\treturn {p.Identifier} as ITrackable;");
            }
            sb.AppendLine("\t\t\tdefault:");
            sb.AppendLine("\t\t\t\treturn null;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t}");
            sb.AppendLine("");

            // ITrackable.GetChildTrackables

            sb.AppendLine(
                "\tpublic IEnumerable<KeyValuePair<object, ITrackable>> GetChildTrackables(bool changedOnly = false)");
            sb.AppendLine("\t{");
            if (trackableProperties.Any())
            {
                foreach (var p in trackableProperties)
                {
                    sb.AppendFormat("\t\tvar trackable{0} = {0} as ITrackable;\n", p.Identifier);
                    sb.AppendFormat(
                        "\t\tif (trackable{0} != null && (changedOnly == false || trackable{0}.Changed))\n",
                        p.Identifier);
                    sb.AppendFormat(
                        "\t\t\tyield return new KeyValuePair<object, ITrackable>(\"{0}\", trackable{0});\n",
                        p.Identifier);
                }
            }
            else
            {
                sb.AppendLine("\t\tyield break;");
            }
            sb.AppendLine("\t}");

            // Property Table

            sb.AppendLine("");
            sb.AppendLine("\tpublic static class PropertyTable");
            sb.AppendLine("\t{");
            foreach (var p in properties)
            {
                sb.Append($"\t\tpublic static readonly PropertyInfo {p.Identifier} = " +
                          $"typeof({typeName}).GetProperty(\"{p.Identifier}\");\n");
            }
            sb.AppendLine("\t}");

            // Property Accessors

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

                sb.AppendLine("");
                sb.AppendLine($"\tprivate {propertyType} _{p.Identifier};");
                sb.AppendLine("");

                var protoMemberAttr = p.AttributeLists.GetAttribute("ProtoMemberAttribute");
                if (protoMemberAttr != null)
                    sb.Append($"\t[ProtoMember{protoMemberAttr?.ArgumentList}] ");
                else
                    sb.Append($"\t");

                sb.AppendLine($"public {propertyType} {propertyName}");
                sb.AppendLine("\t{");
                sb.AppendLine("\t\tget");
                sb.AppendLine("\t\t{");
                sb.AppendLine($"\t\t\treturn _{propertyName};");
                sb.AppendLine("\t\t}");
                sb.AppendLine("\t\tset");
                sb.AppendLine("\t\t{");
                sb.AppendLine($"\t\t\tif (Tracker != null && {propertyName} != value)");
                sb.AppendLine($"\t\t\t\tTracker.TrackSet(PropertyTable.{propertyName}, _{propertyName}, value);");
                sb.AppendLine($"\t\t\t_{propertyName} = value;");
                sb.AppendLine("\t\t}");
                sb.AppendLine("\t}");
            }

            sb.Append("}");

            writer.AddCode(sb.ToString());
        }
コード例 #9
0
        private void GenerateTrackablePocoSurrogateCode(InterfaceDeclarationSyntax idecl, ICodeGenWriter writer)
        {
            var sb = new StringBuilder();
            var typeName = idecl.GetTypeName();
            var trackableClassName = "Trackable" + typeName.Substring(1);
            var className = trackableClassName + "TrackerSurrogate";

            sb.AppendLine("[ProtoContract]");
            sb.AppendLine($"public class {className}");
            sb.AppendLine("{");

            // 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;
                sb.AppendFormat($"\t[ProtoMember{item.Item2.ArgumentList}] ");
                sb.AppendLine($"public EnvelopedObject<{p.Type}> {p.Identifier};");
            }

            // ConvertTrackerToSurrogate

            sb.AppendLine("");
            sb.AppendLine($"\tpublic static implicit operator {className}(TrackablePocoTracker<{typeName}> tracker)");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tif (tracker == null)");
            sb.AppendLine("\t\t\treturn null;");
            sb.AppendLine("");
            sb.AppendLine($"\t\tvar surrogate = new {className}();");
            sb.AppendLine("\t\tforeach(var changeItem in tracker.ChangeMap)");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\tswitch (changeItem.Key.Name)");
            sb.AppendLine("\t\t\t{");
            foreach (var item in propertyWithTags)
            {
                var p = item.Item1;

                sb.AppendLine($"\t\t\t\tcase \"{item.Item1.Identifier}\":");
                sb.AppendLine($"\t\t\t\t\tsurrogate.{p.Identifier} = new EnvelopedObject<{p.Type}>" +
                              $" {{ Value = ({p.Type})changeItem.Value.NewValue }};");

                sb.AppendLine($"\t\t\t\t\tbreak;");
            }
            sb.AppendLine("\t\t\t}");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t\treturn surrogate;");
            sb.AppendLine("\t}");

            // ConvertSurrogateToTracker

            sb.AppendLine("");
            sb.AppendLine($"\tpublic static implicit operator TrackablePocoTracker<{typeName}>({className} surrogate)");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tif (surrogate == null)");
            sb.AppendLine("\t\t\treturn null;");
            sb.AppendLine("");
            sb.AppendLine($"\t\tvar tracker = new TrackablePocoTracker<{typeName}>();");
            foreach (var item in propertyWithTags)
            {
                var p = item.Item1;

                sb.AppendLine($"\t\tif (surrogate.{p.Identifier} != null)");
                sb.Append($"\t\t\ttracker.ChangeMap.Add({trackableClassName}.PropertyTable.{p.Identifier}, " +
                          $"new TrackablePocoTracker<{typeName}>.Change {{ NewValue = surrogate.{p.Identifier}.Value }});\n");
            }
            sb.AppendLine("\t\treturn tracker;");
            sb.AppendLine("\t}");

            sb.Append("}");

            writer.AddCode(sb.ToString());
        }
コード例 #10
0
        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;");
                        }
                    }
                }
            }
        }
コード例 #11
0
        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;");
                }
            }
        }
コード例 #12
0
        private void GenerateTrackableContainerCode(InterfaceDeclarationSyntax idecl, ICodeGenWriter writer)
        {
            var sb = new StringBuilder();
            var typeName = idecl.GetTypeName();
            var className = "Trackable" + typeName.Substring(1);

            var useProtoContract = idecl.AttributeLists.GetAttribute("ProtoContractAttribute") != null;
            if (useProtoContract)
                sb.AppendLine("[ProtoContract]");
            sb.AppendLine($"public partial class {className} : {typeName}");
            sb.AppendLine("{");

            var properties = idecl.GetProperties();

            // Tracker

            sb.AppendLine("\t[IgnoreDataMember]");
            sb.AppendLine($"\tprivate {className}Tracker _tracker;");
            sb.AppendLine("");

            sb.AppendLine("\t[IgnoreDataMember]");
            sb.AppendLine($"\tpublic {className}Tracker Tracker");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tget");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\treturn _tracker;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t\tset");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\t_tracker = value;");
            foreach (var p in properties)
            {
                var propertyName = p.Identifier.ToString();
                sb.AppendLine($"\t\t\t{propertyName}.Tracker = value?.{propertyName}Tracker;");
            }
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t}");
            sb.AppendLine("");

            // ITrackable.Changed

            sb.AppendLine("\tpublic bool Changed { get { return Tracker != null && Tracker.HasChange; } }");
            sb.AppendLine("");

            // ITrackable.Tracker

            sb.AppendLine("\tITracker ITrackable.Tracker");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tget");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\treturn Tracker;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t\tset");
            sb.AppendLine("\t\t{");
            sb.AppendLine($"\t\t\tvar t = ({className}Tracker)value;");
            sb.AppendLine("\t\t\tTracker = t;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t}");
            sb.AppendLine("");

            // ITrackable<T>.Tracker

            sb.AppendLine($"\tITracker<{typeName}> ITrackable<{typeName}>.Tracker");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tget");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\treturn Tracker;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t\tset");
            sb.AppendLine("\t\t{");
            sb.AppendLine($"\t\t\tvar t = ({className}Tracker)value;");
            sb.AppendLine("\t\t\tTracker = t;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t}");
            sb.AppendLine("");

            // IContainerTracker<T>.Tracker

            sb.AppendLine($"\tIContainerTracker<{typeName}> ITrackableContainer<{typeName}>.Tracker");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tget");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\treturn Tracker;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t\tset");
            sb.AppendLine("\t\t{");
            sb.AppendLine($"\t\t\tvar t = ({className}Tracker)value;");
            sb.AppendLine("\t\t\tTracker = t;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t}");
            sb.AppendLine("");

            // ITrackable.GetChildTrackable

            sb.AppendLine("\tpublic ITrackable GetChildTrackable(object name)");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tswitch ((string)name)");
            sb.AppendLine("\t\t{");
            foreach (var p in properties)
            {
                var propertyName = p.Identifier.ToString();
                sb.AppendLine($"\t\t\tcase \"{propertyName}\":");
                sb.AppendLine($"\t\t\t\treturn {propertyName} as ITrackable;");
            }
            sb.AppendLine("\t\t\tdefault:");
            sb.AppendLine("\t\t\t\treturn null;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t}");
            sb.AppendLine("");

            // ITrackable.GetChildTrackables

            sb.AppendLine(
                "\tpublic IEnumerable<KeyValuePair<object, ITrackable>> GetChildTrackables(bool changedOnly = false)");
            sb.AppendLine("\t{");
            if (properties.Any())
            {
                foreach (var p in properties)
                {
                    var propertyType = p.Type.ToString();
                    var propertyName = p.Identifier.ToString();
                    sb.AppendFormat("\t\tvar trackable{0} = {0} as ITrackable;\n", propertyName, propertyType);
                    sb.AppendFormat(
                        "\t\tif (trackable{0} != null && (changedOnly == false || trackable{0}.Changed))\n",
                        propertyName);
                    sb.AppendFormat(
                        "\t\t\tyield return new KeyValuePair<object, ITrackable>(\"{0}\", trackable{0});\n",
                        propertyName);
                }
            }
            else
            {
                sb.AppendLine("\t\tyield break;");
            }
            sb.AppendLine("\t}");

            // Property Accessors

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

                sb.AppendLine("");
                sb.AppendLine($"\tprivate {propertyType} _{propertyName} = new {propertyType}();");
                sb.AppendLine("");

                var protoMemberAttr = p.AttributeLists.GetAttribute("ProtoMemberAttribute");
                if (protoMemberAttr != null)
                    sb.Append($"\t[ProtoMember{protoMemberAttr.ArgumentList}] ");
                else
                    sb.Append("\t");

                sb.AppendLine($"public {propertyType} {propertyName}");
                sb.AppendLine("\t{");
                sb.AppendLine("\t\tget");
                sb.AppendLine("\t\t{");
                sb.AppendLine($"\t\t\treturn _{propertyName};");
                sb.AppendLine("\t\t}");
                sb.AppendLine("\t\tset");
                sb.AppendLine("\t\t{");
                sb.AppendLine($"\t\t\tif (_{propertyName} != null)");
                sb.AppendLine($"\t\t\t\t_{propertyName}.Tracker = null;");
                sb.AppendLine("\t\t\tif (value != null)");
                sb.AppendLine($"\t\t\t\tvalue.Tracker = Tracker?.{propertyName}Tracker;");
                sb.AppendLine($"\t\t\t_{propertyName} = value;");
                sb.AppendLine("\t\t}");
                sb.AppendLine("\t}");

                sb.AppendLine("");
                sb.AppendLine($"\t{propertyType} {typeName}.{propertyName}");
                sb.AppendLine("\t{");
                sb.AppendLine($"\t\tget {{ return _{propertyName}; }}");
                sb.AppendLine($"\t\tset {{ _{propertyName} = ({propertyType})value; }}");
                sb.AppendLine("\t}");
            }

            sb.Append("}");

            writer.AddCode(sb.ToString());
        }
コード例 #13
0
        private void GenerateTrackableContainerTrackerCode(InterfaceDeclarationSyntax idecl, ICodeGenWriter writer)
        {
            var sb = new StringBuilder();
            var typeName = idecl.GetTypeName();
            var className = "Trackable" + typeName.Substring(1) + "Tracker";

            var useProtoContract = idecl.AttributeLists.GetAttribute("ProtoContractAttribute") != null;
            if (useProtoContract)
                sb.AppendLine("[ProtoContract]");

            sb.AppendLine($"public class {className} : IContainerTracker<{typeName}>");
            sb.AppendLine("{");

            // Property Trackers

            var properties = idecl.GetProperties();
            foreach (var p in properties)
            {
                var protoMemberAttr = p.AttributeLists.GetAttribute("ProtoMemberAttribute");
                if (protoMemberAttr != null)
                    sb.Append($"\t[ProtoMember{protoMemberAttr.ArgumentList}] ");
                else
                    sb.Append("\t");

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

            // ToString()

            sb.AppendLine("");
            sb.AppendLine("\tpublic override string ToString()");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tvar sb = new StringBuilder();");
            sb.AppendLine("\t\tsb.Append(\"{ \");");
            sb.AppendLine("\t\tvar first = true;");
            foreach (var p in properties)
            {
                var propertyName = p.Identifier.ToString();
                sb.AppendLine($"\t\tif ({propertyName}Tracker != null && {propertyName}Tracker.HasChange)");
                sb.AppendLine("\t\t{");
                sb.AppendLine("\t\t\tif (first)");
                sb.AppendLine("\t\t\t\tfirst = false;");
                sb.AppendLine("\t\t\telse");
                sb.AppendLine("\t\t\t\tsb.Append(\", \");");
                sb.AppendLine($"\t\t\tsb.Append(\"{propertyName}:\");");
                sb.AppendLine($"\t\t\tsb.Append({propertyName}Tracker);");
                sb.AppendLine("\t\t}");
            }
            sb.AppendLine("\t\tsb.Append(\" }\");");
            sb.AppendLine("\t\treturn sb.ToString();");
            sb.AppendLine("\t}");

            // ITracker.HasChange

            sb.AppendLine("");
            sb.AppendLine("\tpublic bool HasChange");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tget");
            sb.AppendLine("\t\t{");
            sb.AppendLine("\t\t\treturn");
            foreach (var p in properties)
            {
                var propertyName = p.Identifier.ToString();
                sb.AppendLine($"\t\t\t\t({propertyName}Tracker != null && {propertyName}Tracker.HasChange) ||");
            }
            sb.AppendLine("\t\t\t\tfalse;");
            sb.AppendLine("\t\t}");
            sb.AppendLine("\t}");

            // ITracker.HasChange

            sb.AppendLine("");
            sb.AppendLine("\tpublic event TrackerHasChangeSet HasChangeSet");
            sb.AppendLine("\t{");
            sb.AppendLine("\t\tadd { throw new NotImplementedException(); }");
            sb.AppendLine("\t\tremove { throw new NotImplementedException(); }");
            sb.AppendLine("\t}");

            // ITracker.Clear

            sb.AppendLine("");
            sb.AppendLine("\tpublic void Clear()");
            sb.AppendLine("\t{");
            foreach (var p in properties)
            {
                var propertyName = p.Identifier.ToString();
                sb.AppendLine($"\t\tif ({propertyName}Tracker != null)");
                sb.AppendLine($"\t\t\t{propertyName}Tracker.Clear();");
            }
            sb.AppendLine("\t}");

            // ITracker.ApplyTo(Trackable)

            sb.AppendLine("");
            sb.AppendLine("\tpublic void ApplyTo(object trackable)");
            sb.AppendLine("\t{");
            sb.AppendLine($"\t\tApplyTo(({typeName})trackable);");
            sb.AppendLine("\t}");

            sb.AppendLine("");
            sb.AppendLine($"\tpublic void ApplyTo({typeName} trackable)");
            sb.AppendLine("\t{");
            foreach (var p in properties)
            {
                var propertyName = p.Identifier.ToString();
                sb.AppendLine($"\t\tif ({propertyName}Tracker != null)");
                sb.AppendLine($"\t\t\t{propertyName}Tracker.ApplyTo(trackable.{propertyName});");
            }
            sb.AppendLine("\t}");

            // ITracker.ApplyTo(Tracker)

            sb.AppendLine("");
            sb.AppendLine("\tpublic void ApplyTo(ITracker tracker)");
            sb.AppendLine("\t{");
            sb.AppendLine($"\t\tApplyTo(({className})tracker);");
            sb.AppendLine("\t}");

            sb.AppendLine("");
            sb.AppendLine($"\tpublic void ApplyTo(ITracker<{typeName}> tracker)");
            sb.AppendLine("\t{");
            sb.AppendLine($"\t\tApplyTo(({className})tracker);");
            sb.AppendLine("\t}");

            sb.AppendLine("");
            sb.AppendLine($"\tpublic void ApplyTo({className} tracker)");
            sb.AppendLine("\t{");
            foreach (var p in properties)
            {
                var propertyName = p.Identifier.ToString();
                sb.AppendLine($"\t\tif ({propertyName}Tracker != null)");
                sb.AppendLine($"\t\t\t{propertyName}Tracker.ApplyTo(tracker.{propertyName}Tracker);");
            }
            sb.AppendLine("\t}");

            // ITracker.RollbackTo(Trackable)

            sb.AppendLine("");
            sb.AppendLine("\tpublic void RollbackTo(object trackable)");
            sb.AppendLine("\t{");
            sb.AppendLine($"\t\tRollbackTo(({typeName})trackable);");
            sb.AppendLine("\t}");

            sb.AppendLine("");
            sb.AppendLine($"\tpublic void RollbackTo({typeName} trackable)");
            sb.AppendLine("\t{");
            foreach (var p in properties)
            {
                var propertyName = p.Identifier.ToString();
                sb.AppendLine($"\t\tif ({propertyName}Tracker != null)");
                sb.AppendLine($"\t\t\t{propertyName}Tracker.RollbackTo(trackable.{propertyName});");
            }
            sb.AppendLine("\t}");

            // ITracker.RollbackTo(Tracker)

            sb.AppendLine("");
            sb.AppendLine("\tpublic void RollbackTo(ITracker tracker)");
            sb.AppendLine("\t{");
            sb.AppendLine($"\t\tRollbackTo(({className})tracker);");
            sb.AppendLine("\t}");

            sb.AppendLine("");
            sb.AppendLine($"\tpublic void RollbackTo(ITracker<{typeName}> tracker)");
            sb.AppendLine("\t{");
            sb.AppendLine($"\t\tRollbackTo(({className})tracker);");
            sb.AppendLine("\t}");

            sb.AppendLine("");
            sb.AppendLine($"\tpublic void RollbackTo({className} tracker)");
            sb.AppendLine("\t{");
            foreach (var p in properties)
            {
                var propertyName = p.Identifier.ToString();
                sb.AppendLine($"\t\tif ({propertyName}Tracker != null)");
                sb.AppendLine($"\t\t\t{propertyName}Tracker.RollbackTo(tracker.{propertyName}Tracker);");
            }
            sb.AppendLine("\t}");

            sb.Append("}");

            writer.AddCode(sb.ToString());
        }