private void GenerateParameterEntity(ParameterEntity entity)
        {
            var unit = CreateUnit("Models/" + entity.Name + ".cs");
            var ns   = unit.AddNamespace(RootNamespace);
            var type = ns.AddType(new StructDeclaration(entity.Name));

            type.Modifiers = Modifiers.Public | Modifiers.ReadOnly | Modifiers.Partial;

            type.Implements.Add(WellKnownTypes.IGitLabObjectReferenceTypeReference.MakeGeneric(entity.FinalType.ToArgumentTypeReference()));
            type.CustomAttributes.Add(new CustomAttribute(typeof(JsonConverterAttribute))
            {
                Arguments =
                {
                    new CustomAttributeArgument(new TypeOfExpression(WellKnownTypes.GitLabObjectReferenceJsonConverterFactoryTypeReference)),
                },
            });

            // Add Value Property (readonly)
            var valueField    = new FieldDeclaration("_value", GetPropertyTypeRef(entity.FinalType), Modifiers.Private | Modifiers.ReadOnly);
            var valueProperty = new PropertyDeclaration("Value", GetPropertyTypeRef(entity.FinalType))
            {
                Modifiers = Modifiers.Public,
                Getter    = new PropertyAccessorDeclaration
                {
                    Statements = new ReturnStatement(valueField),
                },
            };

            type.AddMember(valueField);
            type.AddMember(valueProperty);

            foreach (var entityRef in entity.Refs)
            {
                var addNullCheck = entityRef.ModelRef.Model != null;

                // Add constructor
                var ctor = type.AddMember(new ConstructorDeclaration()
                {
                    Modifiers = Modifiers.Private,
                    Arguments =
                    {
                        new MethodArgumentDeclaration(GetPropertyTypeRef(entityRef.ModelRef), ToArgumentName(entityRef.Name)),
                    },
                    Statements =
                    {
                        new AssignStatement(valueField, GetAssignExpression()),
                    },
                });

                if (addNullCheck)
                {
                    ctor.Statements.Insert(0, ctor.Arguments[0].CreateThrowIfNullStatement());
                }

                // FromXXX
                var fromMethod = type.AddMember(new MethodDeclaration()
                {
                    Name       = "From" + ToPropertyName(entityRef.Name),
                    Modifiers  = Modifiers.Public | Modifiers.Static,
                    ReturnType = type,
                    Arguments  =
                    {
                        new MethodArgumentDeclaration(GetPropertyTypeRef(entityRef.ModelRef), ToArgumentName(entityRef.Name)),
                    },
                    Statements = new ReturnStatement(new NewObjectExpression(type, new ArgumentReferenceExpression(ToArgumentName(entityRef.Name)))),
                });

                if (addNullCheck)
                {
                    fromMethod.Statements.Insert(0, fromMethod.Arguments[0].CreateThrowIfNullStatement());
                }

                // Add implicit converter
                type.AddMember(new OperatorDeclaration
                {
                    Modifiers  = Modifiers.Public | Modifiers.Static | Modifiers.Implicit,
                    ReturnType = type,
                    Arguments  =
                    {
                        new MethodArgumentDeclaration(GetPropertyTypeRef(entityRef.ModelRef), ToArgumentName(entityRef.Name)),
                    },
                    Statements =
                    {
                        new ReturnStatement(new MethodInvokeExpression(new MemberReferenceExpression(type, fromMethod.Name), new ArgumentReferenceExpression(ToArgumentName(entityRef.Name)))),
                    },
                });

                // Add implicit converter nullable
                var nullableImplicitConverter = type.AddMember(new OperatorDeclaration
                {
                    Modifiers  = Modifiers.Public | Modifiers.Static | Modifiers.Implicit,
                    ReturnType = new TypeReference(type).MakeNullable(),
                    Arguments  =
                    {
                        new MethodArgumentDeclaration(GetPropertyTypeRef(entityRef.ModelRef).MakeNullable(), ToArgumentName(entityRef.Name)),
                    },
                });

                if (entityRef.ModelRef.IsValueType)
                {
                    nullableImplicitConverter.Statements.Add(
                        new ConditionStatement
                    {
                        Condition      = new MemberReferenceExpression(new ArgumentReferenceExpression(ToArgumentName(entityRef.Name)), "HasValue"),
                        TrueStatements = new ReturnStatement(
                            new MethodInvokeExpression(
                                new MemberReferenceExpression(type, fromMethod.Name),
                                new MemberReferenceExpression(new ArgumentReferenceExpression(ToArgumentName(entityRef.Name)), "Value"))),
                        FalseStatements = new ReturnStatement(LiteralExpression.Null()),
                    });
                }
                else
                {
                    nullableImplicitConverter.Statements.Add(
                        new ConditionStatement
                    {
                        Condition = new MethodInvokeExpression(
                            new MemberReferenceExpression(typeof(object), nameof(object.ReferenceEquals)),
                            new ArgumentReferenceExpression(ToArgumentName(entityRef.Name)),
                            LiteralExpression.Null()),
                        TrueStatements  = new ReturnStatement(LiteralExpression.Null()),
                        FalseStatements = new ReturnStatement(new MethodInvokeExpression(new MemberReferenceExpression(type, fromMethod.Name), new ArgumentReferenceExpression(ToArgumentName(entityRef.Name)))),
                    });
                }

                Expression GetAssignExpression()
                {
                    Expression value = new ArgumentReferenceExpression(ToArgumentName(entityRef.Name));

                    foreach (var member in entityRef.PropertyPath)
                    {
                        value = value.CreateMemberReferenceExpression(ToPropertyName(member));
                    }

                    return(value);
                }
            }

            // ToString
            GenerateParameterEntityToString(entity, type, valueProperty);

            // Equals, GetHashCode, ==, !=
            type.Implements.Add(new TypeReference(typeof(IEquatable <>)).MakeGeneric(type));
            GenerateParameterEntityEqualMethod(type);
            GenerateParameterEntityEqualTypedMethod(type, valueProperty);
            GenerateParameterEntityEqualityOperators(type);
            GenerateParameterEntityGetHashCode(type, valueProperty);
        }
Exemplo n.º 2
0
        private void GenerateParameterEntities(NamespaceDeclaration ns, ParameterEntity entity)
        {
            var type = ns.AddType(new StructDeclaration(entity.Name));

            type.Modifiers = Modifiers.Public | Modifiers.ReadOnly | Modifiers.Partial;

            type.Implements.Add(typeof(IReference));
            type.CustomAttributes.Add(new CustomAttribute(typeof(JsonConverterAttribute))
            {
                Arguments =
                {
                    new CustomAttributeArgument(new TypeOfExpression(typeof(ReferenceJsonConverter)))
                }
            });

            // Add Value Property (readonly)
            var valueField    = new FieldDeclaration("_value", GetPropertyTypeRef(entity.FinalType), Modifiers.Private | Modifiers.ReadOnly);
            var valueProperty = new PropertyDeclaration("Value", GetPropertyTypeRef(entity.FinalType))
            {
                Modifiers = Modifiers.Public,
                Getter    = new PropertyAccessorDeclaration
                {
                    Statements = new ReturnStatement(valueField)
                }
            };

            type.AddMember(valueField);
            type.AddMember(valueProperty);

            foreach (var refe in entity.Refs)
            {
                var addNullCheck = refe.ModelRef.Model != null;

                // Add constructor
                var ctor = type.AddMember(new ConstructorDeclaration()
                {
                    Modifiers = Modifiers.Private,
                    Arguments =
                    {
                        new MethodArgumentDeclaration(GetPropertyTypeRef(refe.ModelRef), refe.Name),
                    },
                    Statements =
                    {
                        new AssignStatement(valueField, GetAssignExpression())
                    }
                });

                if (addNullCheck)
                {
                    ctor.Statements.Insert(0, ctor.Arguments[0].CreateThrowIfNullStatement());
                }

                // Add implicit converter
                var implicitOperator = type.AddMember(new OperatorDeclaration()
                {
                    Modifiers  = Modifiers.Public | Modifiers.Static | Modifiers.Implicit,
                    ReturnType = type,
                    Arguments  =
                    {
                        new MethodArgumentDeclaration(GetPropertyTypeRef(refe.ModelRef), refe.Name),
                    },
                    Statements =
                    {
                        new ReturnStatement(new NewObjectExpression(type, new ArgumentReferenceExpression(refe.Name)))
                    }
                });

                if (addNullCheck)
                {
                    implicitOperator.Statements.Insert(0, implicitOperator.Arguments[0].CreateThrowIfNullStatement());
                }

                Expression GetAssignExpression()
                {
                    Expression value = new ArgumentReferenceExpression(refe.Name);

                    foreach (var member in refe.Properties)
                    {
                        value = value.CreateMemberReferenceExpression(ToPropertyName(member));
                    }

                    return(value);
                }
            }
        }