static IEnumerable <string> GetRegisterCollectionTypeMethod(PropertyBagDefinition propertyBag) { var visited = new HashSet <ITypeSymbol>(); foreach (var property in propertyBag.GetPropertyMembers()) { foreach (var line in GetRegisterCollectionTypesRecurse(propertyBag.ContainerType, property.MemberType, visited)) { yield return(line); } } }
public static ClassDeclarationSyntax CreatePropertyBagClassDeclarationSyntax(PropertyBagDefinition propertyBag) { var builder = new StringBuilder(); builder.AppendLine($"[System.Runtime.CompilerServices.CompilerGenerated]"); builder.AppendLine($"class {propertyBag.PropertyBagClassName} : Unity.Properties.ContainerPropertyBag<{propertyBag.ContainerTypeName}>"); builder.AppendLine($"{{"); builder.AppendLine($"public {propertyBag.PropertyBagClassName}()"); builder.AppendLine($"{{"); foreach (var property in propertyBag.GetValidPublicPropertyMembers()) { builder.Append($"AddProperty(new ").Append(property.PropertyClassName).AppendLine("());"); } if (propertyBag.GetValidNonPublicPropertyMembers().Any()) { builder.AppendLine($"#if !{Defines.NET_DOTS}"); foreach (var property in propertyBag.GetValidNonPublicPropertyMembers()) { builder.Append($"AddProperty(new ").Append(property.PropertyClassName).AppendLine("());"); } builder.AppendLine($"#endif"); } foreach (var registerCollectionTypeMethod in GetRegisterCollectionTypeMethod(propertyBag)) { builder.AppendLine(registerCollectionTypeMethod); } builder.Append($"}}"); foreach (var property in propertyBag.GetValidPublicPropertyMembers()) { builder.AppendLine($"[System.Runtime.CompilerServices.CompilerGenerated]"); builder.AppendLine($"class {property.PropertyClassName} : Unity.Properties.Property<{propertyBag.ContainerTypeName}, {property.PropertyTypeName}>"); builder.AppendLine($"{{"); builder.AppendLine($"public override string Name => \"{property.PropertyName}\";"); builder.AppendLine($"public override bool IsReadOnly => {property.IsReadOnly.ToString().ToLower()};"); if (property.HasCustomAttributes) { builder.AppendLine($"public {property.PropertyClassName}()"); builder.AppendLine($"{{"); builder.AppendLine($"#if !{Defines.NET_DOTS}"); var getMemberMethod = property.IsField ? "GetField" : "GetProperty"; builder.AppendLine($"AddAttributes(typeof({propertyBag.ContainerTypeName}).{getMemberMethod}(\"{property.MemberName}\", BindingFlags.Instance | BindingFlags.Public).GetCustomAttributes());"); builder.AppendLine($"#endif"); builder.AppendLine($"}}"); } builder.AppendLine($"public override {property.PropertyTypeName} GetValue(ref {propertyBag.ContainerTypeName} container) => container.{property.PropertyName};"); builder.AppendLine(property.IsReadOnly ? $"public override void SetValue(ref {propertyBag.ContainerTypeName} container, {property.PropertyTypeName} value) => throw new System.InvalidOperationException(\"Property is ReadOnly\");" : $"public override void SetValue(ref {propertyBag.ContainerTypeName} container, {property.PropertyTypeName} value) => container.{property.PropertyName} = value;"); builder.AppendLine($"}}"); } if (propertyBag.GetValidNonPublicPropertyMembers().Any()) { builder.AppendLine($"#if !{Defines.NET_DOTS}"); foreach (var property in propertyBag.GetValidNonPublicPropertyMembers()) { var getMemberMethod = property.IsField ? "GetField" : "GetProperty"; builder.AppendLine($"[System.Runtime.CompilerServices.CompilerGenerated]"); builder.AppendLine($"class {property.PropertyClassName} : Unity.Properties.ReflectedMemberProperty<{propertyBag.ContainerTypeName}, {property.PropertyTypeName}>"); builder.AppendLine($"{{"); builder.AppendLine($" public {property.PropertyClassName}()"); builder.AppendLine($" : base(typeof({property.MemberSymbol.ContainingType}).{getMemberMethod}(\"{property.MemberName}\", BindingFlags.Instance | BindingFlags.NonPublic), \"{property.PropertyName}\")"); builder.AppendLine($" {{"); builder.AppendLine($" }}"); builder.AppendLine($"}}"); } builder.AppendLine($"#endif"); } builder.AppendLine($"}}"); var propertyBagClassDeclarationSyntax = SyntaxFactory.ParseMemberDeclaration(builder.ToString()) as ClassDeclarationSyntax; if (null == propertyBagClassDeclarationSyntax) { throw new Exception($"Failed to construct ClassDeclarationSyntax for ContainerType=[{propertyBag.ContainerTypeName}]"); } return(propertyBagClassDeclarationSyntax); }