Getting Constructor Passed Parameters

I've cast an SqlParameter Newobj opcode's Value parameter to an InstanceInitializer class. I'm trying to find out if the second passed parameter in the constructor is of type HttpContext. I could do this by walking the IL around the Newobj instruction, but I'm wondering if there's a simpler way using the Parameters collection of the Instance Initializer class. I have tried:



InstanceInitializer createdObj = methodInstructions//emoticons/emotion-55.gif" alt="Idea" />.Value as InstanceInitializer;
// Some checking of number of parameters, etc here
if(createdObj.Parameters[1].Type.DeclaringType.Name.Name == "HttpContext")
{
    // Do stuff
}

 


but DeclaringType always seems to be null.I notice that the overload of SqlParameter.c_tor used takes two parameters - String and Object. I don't know if Introspection can tell if the certain object being passed in is of type HttpContext.

The type of code line I'm trying to tag is:


cmd.Parameters.Add(new SqlParameter("@ipAddress", HttpContext.Current.Request.UserHostAddress));
 


Essentially, I'm looking for the


new SqlParameter("@ipAddress", HttpContext.Current.Request.UserHostAddress)
 


bit.


Answer this question

Getting Constructor Passed Parameters

  • amitbadgi

    Michael,

    Thanks for that. I've modified to code to look for SqlParameter method calls, but it doesn't seem to fire on constructor calls (ie SqlParameter newParam = new SqlParameter(string, int);).

  • bebel

    Michael,

    I can't seem to find the code sample anywhere... Any chance you could post the meat of it here

    Cheers,
    James.

  • jerry1

    The samples take a while to propagate after upload.

    Here's the heart of the rule. The XML is embedded as a comment. If anyone knows how to preserve tabs and line spacing when pasting code snippets into a message here, please clue me in. 8)

    Michael



    using System;

    using System.IO;

    using Microsoft.Cci;

    using Microsoft.Tools.FxCop.Sdk;

    using Microsoft.Tools.FxCop.Sdk.Introspection;

    /*

    <Rule TypeName="ExtractsArgumentToMessageBoxShow" Category="Microsoft.Samples" CheckId="SDK1000">

    <Name>Rule that extracts and reports the first argument to MessageBox.Show</Name>

    <Description>This rule demonstrates how to extract a literal argument from the abstract syntax trees exposed by the FxCop metadata reader</Description>

    <Owner>someone</Owner>

    <Url>http://www.gotdotnet.com</Url>

    <Resolution>The following literal argument to MessageBox.Show was found in {0}: '{1}'<Resolution>

    <Email>MikeFanning</Email>

    <MessageLevel Certainty="95">Warning</MessageLevel>

    <FixCategories>NonBreaking</FixCategories>

    </Rule>

    */

    // NOTE: when you change this namespace, be sure to change the

    // namespace referred to in the build script when passing

    // TestRules.xml to csc on the command-line

    namespace Microsoft.Tools.FxCop.Rules.Test

    {

    [CLSCompliant(false)]

    sealed public class ExtractsArgumentToMessageBoxShow: IntrospectionTestRule

    {

    public ExtractsArgumentToMessageBoxShow() : base("ExtractsArgumentToMessageBoxShow") { }

    public override TargetVisibilities TargetVisibility

    { get { return TargetVisibilities.All; }}

    private static AssemblyNode s_WindowsForms;

    private static TypeNode s_MessageBox;

    private Node m_sourceNode;

    private Method m_method;

    public override void BeforeAnalysis()

    {

    if (s_WindowsForms != null) return;

    string redistPath = Path.GetDirectoryName(SystemTypes.SystemAssembly.Location);

    s_WindowsForms = AssemblyNode.GetAssembly(redistPath + @"\System.Windows.Forms.dll");

    s_MessageBox = s_WindowsForms.GetType(

    Identifier.For("System.Windows.Forms"),

    Identifier.For("MessageBox"));

    }

    public override void AfterAnalysis()

    {

    s_WindowsForms.Dispose();

    s_WindowsForms = null;

    s_MessageBox = null;

    }

    public override ProblemCollection Check(Member member)

    {

    m_method = member as Method;

    if (m_method == null) return null;

    VisitMethod(m_method);

    return Problems;

    }

    // Track current source location in order to report

    // exact file/line location. This will not be

    // required in FxCop 1.34

    public override Node Visit(Node node)

    {

    if (node.SourceContext.Document != null)

    m_sourceNode = node;

    return base.Visit(node);

    }

    public override Expression VisitMethodCall(MethodCall call)

    {

    MemberBinding mb = call.Callee as MemberBinding;

    if (mb != null)

    {

    Method callee = mb.BoundMember as Method;

    if (callee == null

    || callee.DeclaringType != s_MessageBox

    || callee.Name.Name != "Show")

    {

    return base.VisitMethodCall(call);

    }

    Expression expression = call.Operands[0];

    Literal literal = expression as Literal;

    if (literal != null)

    {

    string argument = literal.Value as string;

    string method = RuleUtilities.Format(m_method);

    Resolution resolution = GetResolution(

    // The following literal argument to

    method, // MessageBox.Show was found in {0}:

    argument // '{1}'

    );

    Problem problem = new Problem(resolution, m_sourceNode);

    Problems.Add(problem);

    }

    }

    return base.VisitMethodCall(call);

    }

    }

    }



     



  • Mehmet ECEV&amp;#304;T

    It is not. Nearly all of the current rules development architecture is subject to future change. Most of our last efforts in this area had to do with firming up our XML format and the interfaces used to talk to rules (the Check(blah) patterns). This is less likely to change (although we have identified a few more refinements we'll be making to project XML).

    The metadata reader API has not been reviewed or scrubbed at all. There are many issues here that could be addressed: the code does not conform to the guidelines, there is no protection against rules mangling the metadata, there are many constructs that are relevant to source-based analysis only. Finally, the FxCop data flow analysis is in such a transitory phase that we haven't bothered to expose it in a meaningful way at all. (A developer here is actually working on dropping in a complete rewrite that should result in a significant improvement in time-to-analyze).

    In the interests of community, we're glad to provide some help and some sample patterns to solve specific rules development problems on the public forum. The significant caveat here is that any rules developed will very likely need to be modified in the future. Some current functionality might be dropped and not replaced at all. Balancing this, it's likely we'll expose more analysis capabilities as well.

    This is worth emphasizing because every release of FxCop entirely obsoletes the previous, as we refine the analysis, drop noise, add new checks. If the cost of migrating a body of custom rules to the new version prevents updating to a new release of FxCop, that would work counter to the tools purpose. In this case, we'd suggest retaining the previous version (but only to run the custom rules) and to run the new version for the MS-provided analysis. Not all ships will be interested in maintaining two systems, however (this certainly wouldn't fly internally for most development teams).

    Michael



  • staelenss

    Welcome to the world of digging into areas not yet officially supported. 8)

    You need to override VisitConstruct then basically repeat the code I provided. You can create a helper that both VisitContruct and VisitMethodCall can call into. The first argument should be an NaryExpressions, like so:



    public override Expression VisitConstruct(Construct construct)
    {
      MemberBinding mb = construct.Constructor
    as MemberBinding;
      if (mb != null)
      VisitCall(construct, mb.BoundMember);
      return base.VisitConstruct(construct);
    }

    public
    override Expression VisitMethodCall(MethodCall call)
    {
      MemberBinding mb = call.Callee
    as MemberBinding;
      if (mb != null)
      VisitCall(call, mb.BoundMember);
      return base.VisitMethodCall(call);
    }

    private
    void VisitCall(NaryExpression call, Member boundMember)
    {
      // do your work here...
    }

     


  • raviganesh91221

    Is any of this 'officially supported' :)

    Many thanks for the help.

  • MichaelZ

    You're headed straight into the custom rule abyss here. I don't recommend walking the IL for your task and writing to our existing ASTs will mean your rules need to be reworked in the future. Still, I'll try to get some time today to write an example that shows you what you're after.

    More soon,
    Michael

  • mdon

    I just uploaded a custom rule sample to www.gotdotnet.com that demonstrate reporting of any literal argument passed to MessageBox.Show. Also demonstrates correct pattern for initializing and nulling static data in FxCop rules.

    I'll also post this sample pattern to this board as an FAQ once I figure out how to retain formatting information properly on pasting in from VS.

    As always, I need to advise that this code snippet is likely to break in the next release of FxCop, due to ongoing changes in our rule architecture and metadata reader.

    Michael

  • Getting Constructor Passed Parameters