public void CSharpCodeGenerator_FieldDeclaration()
        {
            var type = new ClassDeclaration("Sample");

            type.AddMember(new FieldDeclaration("_a", typeof(int)));
            type.AddMember(new FieldDeclaration("_b", typeof(Type), Modifiers.Private));
            type.AddMember(new FieldDeclaration("_c", typeof(int), Modifiers.Protected, 10));

            var generator = new CSharpCodeGenerator();
            var result    = generator.Write(type);

            Assert.That.StringEquals(@"class Sample
{
    int _a;

    private System.Type _b;

    protected int _c = 10;
}
", result);
        }
        public void CSharpCodeGenerator_EventDeclaration()
        {
            var type = new ClassDeclaration("Sample");

            type.AddMember(new EventFieldDeclaration("A", typeof(EventHandler), Modifiers.Public));

            var generator = new CSharpCodeGenerator();
            var result    = generator.Write(type);

            Assert.That.StringEquals(@"class Sample
{
    public event System.EventHandler A;
}
", result);
        }
        private static MethodDeclaration GenerateExplicitImplementationMethod(ClassDeclaration clientClass, InterfaceDeclaration clientInterface, Method method, TypeReference requestType)
        {
            var m = clientClass.AddMember(new MethodDeclaration(GetMethodName(method)));

            m.PrivateImplementationType = clientInterface;
            GenerateMethodSignature(method, m, requestType, out _, out _, out _);
            foreach (var arg in m.Arguments)
            {
                arg.DefaultValue = null;
            }

            m.Statements = new ReturnStatement(
                new MethodInvokeExpression(
                    new MemberReferenceExpression(new ThisExpression(), method.MethodGroup.Name + '_' + m.Name),
                    m.Arguments.Select(arg => new ArgumentReferenceExpression(arg)).ToArray()));
            return(m);
        }
        public void CSharpCodeGenerator_Constructor()
        {
            var type = new ClassDeclaration("Sample");
            var ctor = type.AddMember(new ConstructorDeclaration());

            ctor.Modifiers = Modifiers.Internal;
            var generator = new CSharpCodeGenerator();
            var result    = generator.Write(type);

            Assert.That.StringEquals(@"class Sample
{
    internal Sample()
    {
    }
}
", result);
        }
        public void CSharpCodeGenerator_Constructor_ThisWithArgs()
        {
            var type = new ClassDeclaration("Sample");
            var ctor = type.AddMember(new ConstructorDeclaration());

            ctor.Initializer = new ConstructorThisInitializer(new LiteralExpression("arg"));
            ctor.Modifiers   = Modifiers.Public;

            var generator = new CSharpCodeGenerator();
            var result    = generator.Write(type);

            Assert.That.StringEquals(@"class Sample
{
    public Sample()
        : this(""arg"")
    {
    }
}
", result);
        }
        private static MethodDeclaration GenerateMethod(ClassDeclaration clientClass, Method method, TypeReference requestType)
        {
            var m = clientClass.AddMember(new MethodDeclaration(method.MethodGroup.Name + '_' + GetMethodName(method)));

            m.SetData("Method", method);
            var buildUrlMethod = GenerateBuildUrlMethod(clientClass, method, requestType);

            GenerateMethodSignature(method, m, requestType, out var requestArgument, out var requestOptionsArgument, out var cancellationTokenArgument);
            m.Modifiers = Modifiers.Private;
            if (method.MethodType != MethodType.GetPaged)
            {
                m.Modifiers |= Modifiers.Async;
            }

            // Method body
            m.Statements = new StatementCollection();

            // 1. Create url from parameters
            var buildUrlExpression = new MethodInvokeExpression(new MemberReferenceExpression(new TypeReference(clientClass), buildUrlMethod));

            if (buildUrlMethod.Arguments.Count > 0)
            {
                buildUrlExpression.Arguments.Add(requestArgument);
            }

            var urlVariable = new VariableDeclarationStatement(typeof(string), "url", buildUrlExpression);

            m.Statements.Add(urlVariable);

            if (method.MethodType == MethodType.GetPaged)
            {
                // return new Meziantou.GitLab.PagedResponse<MergeRequest>(this, url, requestOptions);
                m.Statements.Add(new ReturnStatement(new NewObjectExpression(m.ReturnType !.Clone(), new ThisExpression(), urlVariable, requestOptionsArgument)));
            }
            else
            {
                // 2. Create HttpRequestMessage object
                var requestVariable = new VariableDeclarationStatement(typeof(HttpRequestMessage), "requestMessage", new NewObjectExpression(typeof(HttpRequestMessage)));
                var usingStatement  = new UsingStatement()
                {
                    Statement = requestVariable, Body = new StatementCollection()
                };
                m.Statements.Add(usingStatement);
                var statements = usingStatement.Body;

                statements.Add(new AssignStatement(new MemberReferenceExpression(requestVariable, nameof(HttpRequestMessage.Method)), GetHttpMethod(method.MethodType)));
                statements.Add(new AssignStatement(new MemberReferenceExpression(requestVariable, nameof(HttpRequestMessage.RequestUri)), new NewObjectExpression(typeof(Uri), urlVariable, new MemberReferenceExpression(typeof(UriKind), nameof(UriKind.RelativeOrAbsolute)))));

                CreateBodyArgument(method, statements, requestArgument, requestVariable);

                // 3. Send request
                // var response = await SendAsync(request, options, cancellationToken).ConfigureAwait(false);
                var responseVariable = new VariableDeclarationStatement(WellKnownTypes.HttpResponseTypeReference.MakeNullable(), "response", LiteralExpression.Null());
                statements.Add(responseVariable);
                var responseTry = new TryCatchFinallyStatement()
                {
                    Try = new StatementCollection()
                };
                statements.Add(responseTry);
                responseTry.Try.Add(new AssignStatement(responseVariable, new AwaitExpression(new MethodInvokeExpression(new MemberReferenceExpression(new ThisExpression(), "SendAsync"), requestVariable, requestOptionsArgument, cancellationTokenArgument)).ConfigureAwait(false)));

                // Dispose reponse in catch if Stream or in finally if not stream
                var disposeReponseStatements = new ConditionStatement()
                {
                    Condition      = new BinaryExpression(BinaryOperator.NotEquals, responseVariable, LiteralExpression.Null()),
                    TrueStatements = responseVariable.CreateInvokeMethodExpression("Dispose"),
                };

                if (method.ReturnType == ModelRef.File)
                {
                    responseTry.Catch = new CatchClauseCollection
                    {
                        new CatchClause()
                        {
                            Body = disposeReponseStatements,
                        },
                    };

                    responseTry.Catch[0].Body.Add(new ThrowStatement());
                }
                else
                {
                    responseTry.Finally = disposeReponseStatements;
                }

                // 4. Convert and return response object
                //    if (response.StatusCode == HttpStatusCode.NotFound) return default;
                if (method.MethodType == MethodType.Get)
                {
                    responseTry.Try.Add(new ConditionStatement()
                    {
                        Condition      = new BinaryExpression(BinaryOperator.Equals, responseVariable.CreateMemberReferenceExpression("StatusCode"), new MemberReferenceExpression(typeof(HttpStatusCode), "NotFound")),
                        TrueStatements = new ReturnStatement(new DefaultValueExpression()),
                    });
                }

                // await response.EnsureStatusCodeAsync(cancellationToken).ConfigureAwait(false);
                responseTry.Try.Add(new AwaitExpression(new MethodInvokeExpression(new MemberReferenceExpression(responseVariable, "EnsureStatusCodeAsync"), cancellationTokenArgument)).ConfigureAwait(false));

                if (method.ReturnType != null)
                {
                    // var result = await response.ToObjectAsync<T>(cancellationToken).ConfigureAwait(false);
                    var resultVariable = new VariableDeclarationStatement(m.ReturnType.Parameters[0].MakeNullable(), "result");
                    responseTry.Try.Add(resultVariable);
                    if (method.MethodType == MethodType.Get && method.ReturnType == ModelRef.File)
                    {
                        resultVariable.InitExpression = new AwaitExpression(responseVariable.CreateInvokeMethodExpression("ToStreamAsync", cancellationTokenArgument)).ConfigureAwait(false);
                    }
                    else if (method.MethodType == MethodType.GetCollection)
                    {
                        resultVariable.InitExpression = new AwaitExpression(responseVariable.CreateInvokeMethodExpression("ToCollectionAsync", new TypeReference[] { method.ReturnType.ToPropertyTypeReference() }, cancellationTokenArgument)).ConfigureAwait(false);
                    }
                    else
                    {
                        resultVariable.InitExpression = new AwaitExpression(responseVariable.CreateInvokeMethodExpression("ToObjectAsync", new TypeReference[] { method.ReturnType.ToPropertyTypeReference() }, cancellationTokenArgument)).ConfigureAwait(false);
                    }

                    // if (result is null)
                    //   throw new GitLabException(response.RequestMethod, response.RequestUri, response.StatusCode, $"The response cannot be converted to '{typeof(T)}' because the body is null or empty");
                    if (method.MethodType != MethodType.Get)
                    {
                        responseTry.Try.Add(new ConditionStatement()
                        {
                            Condition      = new BinaryExpression(BinaryOperator.Equals, resultVariable, LiteralExpression.Null()),
                            TrueStatements = new ThrowStatement(new NewObjectExpression(WellKnownTypes.GitLabExceptionTypeReference,
                                                                                        responseVariable.CreateMemberReferenceExpression("RequestMethod"),
                                                                                        responseVariable.CreateMemberReferenceExpression("RequestUri"),
                                                                                        responseVariable.CreateMemberReferenceExpression("StatusCode"),
                                                                                        new LiteralExpression($"The response cannot be converted to '{method.ReturnType.ToPropertyTypeReference().ClrFullTypeName}' because the body is null or empty"))),
                        });
                    }

                    responseTry.Try.Add(new ReturnStatement(resultVariable));
                }
            }

            return(m);
        private static MethodDeclaration GenerateBuildUrlMethod(ClassDeclaration clientClass, Method method, TypeReference requestType)
        {
            var m = clientClass.AddMember(new MethodDeclaration(method.MethodGroup.Name + '_' + GetMethodName(method) + "_BuildUrl"));

            m.Modifiers  = Modifiers.Private | Modifiers.Static;
            m.ReturnType = typeof(string);

            // Method body
            m.Statements = new StatementCollection();

            var urlVariable = new VariableDeclarationStatement(typeof(string), "url");

            m.Statements.Add(urlVariable);

            // 1. Create url from parameters
            var parameters = method.Parameters.Where(p => GetParameterLocation(method, p) == ParameterLocation.Url).ToList();

            if (parameters.Any())
            {
                var requestArgument = m.AddArgument("request", requestType);

                // [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "<Pending>")]
                m.CustomAttributes.Add(new CustomAttribute(typeof(SuppressMessageAttribute))
                {
                    Arguments =
                    {
                        new CustomAttributeArgument(new LiteralExpression("Reliability")),
                        new CustomAttributeArgument(new LiteralExpression("CA2000:Dispose objects before losing scope")),
                        new CustomAttributeArgument("Justification",                                                     new LiteralExpression("The rule doesn't understand ref struct")),
                    },
                });

                var segments   = GetSegments(method.UrlTemplate);
                var urlBuilder = new VariableDeclarationStatement(
                    WellKnownTypes.UrlBuilderTypeReference, "urlBuilder",
                    new NewObjectExpression(WellKnownTypes.UrlBuilderTypeReference));
                var urlUsingStatement = new UsingStatement()
                {
                    Statement = urlBuilder,
                    Body      = new StatementCollection(),
                };
                var usingStatements = urlUsingStatement.Body;
                m.Statements.Add(urlUsingStatement);

                foreach (var segment in segments)
                {
                    if (segment[0] == ':')
                    {
                        var param = parameters.SingleOrDefault(p => p.Name == segment[1..]);
                        if (param == null)
                        {
                            throw new InvalidOperationException($"Parameter '{segment}' is not mapped for method '{method.UrlTemplate}'");
                        }

                        AddParameter(param, parameterDelimiterVariable: null, encoded: true);
                        parameters.Remove(param);
                    }
                    else if (segment[0] == '*')
                    {
                        var param = parameters.SingleOrDefault(p => p.Name == segment[1..]);
                        if (param == null)
                        {
                            throw new InvalidOperationException($"Parameter '{segment}' is not mapped for method '{method.UrlTemplate}'");
                        }

                        AddParameter(param, parameterDelimiterVariable: null, encoded: false);
                        parameters.Remove(param);
                    }
                    else if (segment.StartsWith("[.", StringComparison.Ordinal))
                    {
                        var param = parameters.SingleOrDefault(p => p.Name == segment[2..^ 1]);
                        if (param == null)
                        {
                            throw new InvalidOperationException($"Parameter '{segment}' is not mapped for method '{method.UrlTemplate}'");
                        }

                        AddParameter(param, parameterDelimiterVariable: null, encoded: false, prefix: ".");
                        parameters.Remove(param);
                    }
                    else
                    {
                        usingStatements.Add(urlBuilder.CreateInvokeMethodExpression("Append", new LiteralExpression(segment)));
                    }
                }

                if (parameters.Any())
                {
                    var separator = new VariableDeclarationStatement(typeof(char), "separator", new LiteralExpression('?'));
                    usingStatements.Add(separator);

                    foreach (var param in parameters)
                    {
                        AddParameter(param, separator, encoded: true);
                    }
                }

                usingStatements.Add(new AssignStatement(urlVariable, urlBuilder.CreateInvokeMethodExpression("ToString")));

                void AddParameter(MethodParameter param, VariableDeclarationStatement parameterDelimiterVariable, bool encoded, string prefix = null)
                {
                    var appendParameterMethodName = encoded ? "AppendParameter" : "AppendRawParameter";

                    void AddSeparator(StatementCollection statements)
                    {
                        if (parameterDelimiterVariable != null)
                        {
                            statements.Add(urlBuilder.CreateInvokeMethodExpression("Append", parameterDelimiterVariable));
                            statements.Add(new AssignStatement(parameterDelimiterVariable, new LiteralExpression('&')));

                            if (!param.Options.HasFlag(MethodParameterOptions.CustomMapping))
                            {
                                statements.Add(urlBuilder.CreateInvokeMethodExpression("Append", new LiteralExpression(param.Name + '=')));
                            }
                        }
                    }

                    void AppendPrefix(StatementCollection statements)
                    {
                        if (!string.IsNullOrEmpty(prefix))
                        {
                            statements.Add(urlBuilder.CreateInvokeMethodExpression("Append", prefix));
                        }
                    }

                    if (param.Type.IsParameterEntity)
                    {
                        var propertyName      = param.Type.ParameterEntity.FinalType == ModelRef.Object ? "ValueAsString" : "Value";
                        var hasValueCondition = new ConditionStatement
                        {
                            Condition      = CreatePropertyReference().CreateMemberReferenceExpression(nameof(Nullable <int> .HasValue)),
                            TrueStatements = new StatementCollection(),
                        };

                        AddSeparator(hasValueCondition.TrueStatements);
                        AppendPrefix(hasValueCondition.TrueStatements);
                        var parameterValue = FormatValue(param.Type, CreatePropertyReference().CreateInvokeMethodExpression("GetValueOrDefault").CreateMemberReferenceExpression(propertyName));

                        if (param.Options.HasFlag(MethodParameterOptions.CustomMapping))
                        {
                            hasValueCondition.TrueStatements.Add(urlBuilder
                                                                 .CreateInvokeMethodExpression(
                                                                     "AppendParameter",
                                                                     param.Name,
                                                                     parameterValue));
                        }
                        else
                        {
                            hasValueCondition.TrueStatements.Add(urlBuilder
                                                                 .CreateInvokeMethodExpression(
                                                                     appendParameterMethodName,
                                                                     parameterValue));
                        }

                        urlUsingStatement.Body.Add(hasValueCondition);
                    }
                    else
                    {
                        var isValueType = param.Type.IsValueType && !param.Type.IsCollection;

                        var hasValueCondition = new ConditionStatement
                        {
                            Condition = isValueType ? CreatePropertyReference().CreateMemberReferenceExpression("HasValue") :
                                        new UnaryExpression(UnaryOperator.Not,
                                                            new MethodInvokeExpression(
                                                                new MemberReferenceExpression(new TypeReference(typeof(object)), "ReferenceEquals"),
                                                                CreatePropertyReference(), LiteralExpression.Null())),
                            TrueStatements = new StatementCollection(),
                        };

                        AddSeparator(hasValueCondition.TrueStatements);
                        AppendPrefix(hasValueCondition.TrueStatements);

                        Expression parameterValue = isValueType ? CreatePropertyReference().CreateInvokeMethodExpression("GetValueOrDefault") : CreatePropertyReference();

                        if (param.Options.HasFlag(MethodParameterOptions.CustomMapping))
                        {
                            hasValueCondition.TrueStatements.Add(urlBuilder
                                                                 .CreateInvokeMethodExpression(
                                                                     "AppendParameter",
                                                                     param.Name,
                                                                     parameterValue));
                        }
                        else
                        {
                            var appendMethod = new MethodInvokeExpression(
                                new MemberReferenceExpression(urlBuilder, appendParameterMethodName),
                                FormatValue(param.Type, parameterValue));

                            hasValueCondition.TrueStatements.Add(appendMethod);
                        }

                        urlUsingStatement.Body.Add(hasValueCondition);
                    }

                    MemberReferenceExpression CreatePropertyReference()
                    {
                        return(requestArgument.CreateMemberReferenceExpression(ToPropertyName(param.Name)));
                    }
                }
            }
            else
            {
                m.Statements.Add(new AssignStatement(urlVariable, new LiteralExpression(method.UrlTemplate)));
            }

            m.Statements.Add(new ReturnStatement(urlVariable));
            return(m);
        }
Esempio n. 8
0
        private MethodDeclaration GenerateMethod(ClassDeclaration clientClass, Method method)
        {
            var m = clientClass.AddMember(new MethodDeclaration(method.Name + "Async"));

            m.SetData("Method", method);
            GenerateMethodSignature(method, m, out var arguments, out var pageArgument, out var requestOptionsArgument, out var cancellationTokenArgument);
            m.Modifiers = Modifiers.Public;

            // Method body
            m.Statements = new StatementCollection();

            var urlBuilder = new VariableDeclarationStatement(
                typeof(UrlBuilder), "urlBuilder",
                new TypeReference(typeof(UrlBuilder))
                .CreateInvokeMethodExpression("Get", method.UrlTemplate));

            m.Statements.Add(urlBuilder);

            foreach (var param in method.Parameters.Where(p => GetParameterLocation(method, p) == ParameterLocation.Url))
            {
                if (param.Type.IsParameterEntity)
                {
                    if (param.Type.IsNullable)
                    {
                        var hasValueCondition = new ConditionStatement
                        {
                            Condition      = arguments[param].CreateMemberReferenceExpression(nameof(Nullable <int> .HasValue)),
                            TrueStatements = urlBuilder.CreateInvokeMethodExpression(nameof(UrlBuilder.WithValue), param.Name, arguments[param].CreateMemberReferenceExpression(nameof(Nullable <int> .Value), "Value"))
                        };
                        m.Statements.Add(hasValueCondition);
                    }
                    else
                    {
                        m.Statements.Add(urlBuilder.CreateInvokeMethodExpression(nameof(UrlBuilder.WithValue), param.Name, arguments[param].CreateMemberReferenceExpression("Value")));
                    }
                }
                else
                {
                    m.Statements.Add(urlBuilder.CreateInvokeMethodExpression(nameof(UrlBuilder.WithValue), param.Name, arguments[param]));
                }
            }

            if (pageArgument != null)
            {
                var pageCondition = new ConditionStatement()
                {
                    Condition      = new BinaryExpression(BinaryOperator.NotEquals, pageArgument, new LiteralExpression(null)),
                    TrueStatements = new StatementCollection
                    {
                        new ConditionStatement()
                        {
                            Condition      = new BinaryExpression(BinaryOperator.GreaterThan, pageArgument.CreateMemberReferenceExpression(nameof(PageOptions.PageIndex)), new LiteralExpression(0)),
                            TrueStatements = new StatementCollection
                            {
                                urlBuilder.CreateInvokeMethodExpression(nameof(UrlBuilder.WithValue), "page", pageArgument.CreateMemberReferenceExpression(nameof(PageOptions.PageIndex)))
                            }
                        },
                        new ConditionStatement()
                        {
                            Condition      = new BinaryExpression(BinaryOperator.GreaterThan, pageArgument.CreateMemberReferenceExpression(nameof(PageOptions.PageSize)), new LiteralExpression(0)),
                            TrueStatements = new StatementCollection
                            {
                                urlBuilder.CreateInvokeMethodExpression(nameof(UrlBuilder.WithValue), "per_page", pageArgument.CreateMemberReferenceExpression(nameof(PageOptions.PageSize)))
                            }
                        },
                        new ConditionStatement()
                        {
                            Condition      = new BinaryExpression(BinaryOperator.Equals, pageArgument.CreateMemberReferenceExpression(nameof(PageOptions.OrderBy), nameof(OrderBy.Name)).CreateIsNullOrEmptyExpression(), new LiteralExpression(false)),
                            TrueStatements = new StatementCollection
                            {
                                urlBuilder.CreateInvokeMethodExpression(nameof(UrlBuilder.WithValue), "order_by", pageArgument.CreateMemberReferenceExpression(nameof(PageOptions.OrderBy), nameof(OrderBy.Name))),
                                urlBuilder.CreateInvokeMethodExpression(nameof(UrlBuilder.WithValue), "sort", pageArgument.CreateMemberReferenceExpression(nameof(PageOptions.OrderBy), nameof(OrderBy.Direction)))
                            }
                        }
                    }
                };

                m.Statements.Add(pageCondition);
            }

            var url = new VariableDeclarationStatement(typeof(string), "url", urlBuilder.CreateInvokeMethodExpression(nameof(UrlBuilder.Build)));

            m.Statements.Add(url);

            var bodyArgument = CreateBodyArgument(method, m);

            switch (method.MethodType)
            {
            case MethodType.Get:
                if (method.ReturnType.IsCollection)
                {
                    m.Statements.Add(new ReturnStatement(new ThisExpression().CreateInvokeMethodExpression("GetCollectionAsync", new TypeReference[] { method.ReturnType }, url, requestOptionsArgument, cancellationTokenArgument)));
                }
                else
                {
                    m.Statements.Add(new ReturnStatement(new ThisExpression().CreateInvokeMethodExpression("GetAsync", new TypeReference[] { method.ReturnType }, url, requestOptionsArgument, cancellationTokenArgument)));
                }

                break;

            case MethodType.GetPaged:
                m.Statements.Add(new ReturnStatement(new ThisExpression().CreateInvokeMethodExpression("GetPagedAsync", new TypeReference[] { method.ReturnType }, url, requestOptionsArgument, cancellationTokenArgument)));
                break;

            case MethodType.Put:
                var putArgs = new List <Expression>();
                putArgs.Add(url);
                putArgs.Add((Expression)bodyArgument ?? new LiteralExpression(null));
                putArgs.Add(requestOptionsArgument);
                putArgs.Add(cancellationTokenArgument);
                m.Statements.Add(new ReturnStatement(new ThisExpression().CreateInvokeMethodExpression("PutJsonAsync", new TypeReference[] { method.ReturnType }, putArgs.ToArray())));
                break;

            case MethodType.Post:
                var postArgs = new List <Expression>();
                postArgs.Add(url);
                postArgs.Add((Expression)bodyArgument ?? new LiteralExpression(null));
                postArgs.Add(requestOptionsArgument);
                postArgs.Add(cancellationTokenArgument);
                if (method.ReturnType != null)
                {
                    m.Statements.Add(new ReturnStatement(new ThisExpression().CreateInvokeMethodExpression("PostJsonAsync", new TypeReference[] { method.ReturnType }, postArgs.ToArray())));
                }
                else
                {
                    m.Statements.Add(new ReturnStatement(new ThisExpression().CreateInvokeMethodExpression("PostJsonAsync", postArgs.ToArray())));
                }
                break;

            case MethodType.Delete:
                m.Statements.Add(new ReturnStatement(new ThisExpression().CreateInvokeMethodExpression("DeleteAsync", url, requestOptionsArgument, cancellationTokenArgument)));
                break;

            default:
                throw new NotSupportedException($"Method {method.MethodType} is not supported");
            }

            return(m);
        }
        private void AddCopyToMethod(ClassDeclaration classDecl, TableSchema table)
        {
            var method = new CodeMemberMethod();
            method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            method.Name = "CopyTo";

            string argName = this.NameProvider.GetArgumentName(table.Name);
            var parameter = new CodeParameterDeclarationExpression(this.NameProvider.GetClassName(table), argName);
            method.Parameters.Add(parameter);
            foreach (ColumnSchema column in table.NonKeyColumns)
            {
                var lhs = new CodePropertyReferenceExpression(new CodeArgumentReferenceExpression(argName), this.NameProvider.GetPropertyName(column));
                var rhs = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), this.NameProvider.GetPropertyName(column));
                method.Statements.Add(new CodeAssignStatement(lhs, rhs));
            }
            foreach (ColumnSchema column in table.ForeignKeys)
            {
                string propertyName = this.NameProvider.GetPropertyName(column.Name.Replace("ID", "").Replace("_id", ""));
                var lhs = new CodePropertyReferenceExpression(new CodeArgumentReferenceExpression(argName), propertyName);
                var rhs = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), propertyName);
                method.Statements.Add(new CodeAssignStatement(lhs, rhs));
            }
            classDecl.AddMember(method);
        }