Как я могу получить значение параметра, переданного методу в пользовательском правиле в FxCop? - PullRequest
2 голосов
/ 16 августа 2010

По некоторым причинам в нашем веб-приложении ASP.NET не рекомендуется использовать Response.Redirect("something", True).Его следует использовать с False для параметра endResponse.Мы хотим обеспечить это с помощью специального правила FxCop.Мне удалось найти использование Response.Redirect, но теперь я хочу найти значение аргумента endResponse.Как я могу это сделать?

Мы используем следующий код:

public override ProblemCollection Check(Member member)
{
    var method = member as Method;
    if (method != null)
    {
        foreach (var instruction in method.Instructions)
        {
            switch (instruction.OpCode)
            {
                case OpCode.Call:
                case OpCode.Callvirt:
                case OpCode.Newobj:
                    var call = (Method) instruction.Value;
                    if (call == null)
                    {
                        break;
                    }
                    if (call.Name.Name != "Redirect")
                    {
                        break;
                    }
                    if (call.Parameters.Count == 1)
                    {
                        //Redirect(url)
                        var resolution = GetResolution();
                        var problem = new Problem(resolution);
                        Problems.Add(problem);
                    }
                    if (call.Parameters.Count == 2)
                    {
                        VisitStatements(call.Body.Statements);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    return Problems;
}

public override void VisitExpression(Expression expression)
{
    var methodCall = expression as MethodCall;
    if (methodCall == null)
    {
        return;
    }

    foreach (var operand in methodCall.Operands)
    {
        if (operand.Type.Name.Name == "Int16" || operand.Type.Name.Name == "Int32" || operand.Type.Name.Name == "Int64")
        {
            var literal = operand as Literal;
            if (literal != null && literal.Value is int)
            {
                var literalValue = (int)literal.Value;
                if (literalValue == 1)
                {
                    var resolution = GetResolution();
                    var problem = new Problem(resolution);
                    Problems.Add(problem);
                }
            }
        }
    }
}

Я использовал Introspector и думал, что параметр endResponse был целым числомза кулисами, но я не уверен больше.В любом случае, похоже, что в methodCall.Operands.

нет логических значений. У кого-нибудь когда-нибудь была подобная ситуация, когда вам нужно проверить фактическое значение параметра, переданного методу?

1 Ответ

1 голос
/ 16 августа 2010

Хотя тип параметра на самом деле является System.Boolean, синтаксический анализатор FxCop IL рассматривает его как целое число. Вот упрощенная версия правила, которое должно работать (при условии, что вы хотите, чтобы не буквальные значения endResponse вызывали нарушение правила):

    public override ProblemCollection Check(Member member)
    {
        Method method = member as Method;
        if (method != null)
        {
            this.Visit(method.Body);
        }

        return this.Problems;
    }

    public override void VisitMethodCall(MethodCall call)
    {
        base.VisitMethodCall(call);

        Method targetMethod = (Method)((MemberBinding)call.Callee).BoundMember;
        if (targetMethod.DeclaringType.FullName.Equals("System.Web.HttpResponse", StringComparison.Ordinal) &&
            targetMethod.Name.Name.Equals("Redirect", StringComparison.Ordinal))
        {
            bool callIsAcceptable = false;

            if (targetMethod.Parameters.Count == 2)
            {
                Expression endResponseOperand = call.Operands[1];
                if (endResponseOperand.NodeType == NodeType.Literal)
                {
                    if ((int)((Literal)endResponseOperand).Value == 1)
                    {
                        callIsAcceptable = true;
                    }
                }
            }

            if (!callIsAcceptable)
            {
                this.Problems.Add(new Problem(this.GetResolution(), call));
            }
        }
    }
...