Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 确定一个方法是否调用另一个包含新语句的程序集中的方法,反之亦然_C#_.net_Fxcop_Call Graph - Fatal编程技术网

C# 确定一个方法是否调用另一个包含新语句的程序集中的方法,反之亦然

C# 确定一个方法是否调用另一个包含新语句的程序集中的方法,反之亦然,c#,.net,fxcop,call-graph,C#,.net,Fxcop,Call Graph,我想编写一个规则,如果在标记有特定属性的方法调用的任何方法中进行对象分配,则该规则将失败 到目前为止,通过使用CallGraph.CallersFor()对调用我的方法的所有方法进行迭代,查看这些父方法中是否有该属性,我已经做到了这一点 这适用于在与要检查的方法相同的程序集中检查父方法,但是在联机阅读时,似乎有一次CallGraph.CallersFor()查看了所有程序集,但现在没有 问题:是否有方法获取调用给定方法的方法列表,包括不同程序集中的方法 备选答案:如果上述方法不可行,如何循环使用

我想编写一个规则,如果在标记有特定属性的方法调用的任何方法中进行对象分配,则该规则将失败

到目前为止,通过使用
CallGraph.CallersFor()
对调用我的方法的所有方法进行迭代,查看这些父方法中是否有该属性,我已经做到了这一点

这适用于在与要检查的方法相同的程序集中检查父方法,但是在联机阅读时,似乎有一次
CallGraph.CallersFor()
查看了所有程序集,但现在没有

问题:是否有方法获取调用给定方法的方法列表,包括不同程序集中的方法

备选答案:如果上述方法不可行,如何循环使用给定方法调用的每个方法,包括不同程序集中的方法


示例:

-----In Assembly A

public class ClassA
{
    public MethodA()
    {
        MethodB();
    }

    public MethodB()
    {
        object o = new object(); // Allocation i want to break the rule
        // Currently my rule walks up the call tree,
        // checking for a calling method with the NoAllocationsAllowed attribute.
        // Problem is, because of the different assemblies,
        // it can't go from ClassA.MethodA to ClassB.MethodB.
    }
}


----In Assembly B

public var ClassAInstance = new ClassA();

public class ClassB
{
    [NoAllocationsAllowed] // Attribute that kicks off the rule-checking.
    public MethodA()
    {
        MethodB();
    }

    public MethodB()
    {
        ClassAInstance.MethodA();
    }
}

我真的不介意规则在哪里报告错误,在这个阶段获得错误就足够了。

您是否用这种方式尝试过

    StackTrace stackTrace = new StackTrace();
    MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
    object [] items = methodBase.GetCustomAttributes(typeof (NoAllocationsAllowed));
    if(items.Length > 0)
        //do whatever you want! 

我通过在FxCop项目中添加所有引用的DLL并使用下面的代码来解决这个问题,该代码手动构建调用树(它还添加了对派生类的调用,以解决我遇到的另一个问题)

公共类CallGraphBuilder:BinaryReadOnlyVisitor
{
公共字典子类型;
公共字典调用者方法;
私有方法_CurrentMethod;
公共调用GraphBuilder()
:base()
{
CallersOfMethod=新字典();
ChildTypes=newdictionary();
}
公共覆盖无效访问方法(方法)
{
_CurrentMethod=方法;
基本访问方法(方法);
}
公共void CreateTypesTree(组装节点组件)
{
foreach(组件类型中的变量类型)
{
if(Type.FullName!=“System.Object”)
{
TypeNode BaseType=Type.BaseType;
if(BaseType!=null&&BaseType.FullName!=“System.Object”)
{
如果(!ChildTypes.ContainsKey(BaseType))
Add(BaseType,newlist());
如果(!ChildTypes[BaseType].包含(类型))
子类型[BaseType]。添加(类型);
}
}
}
}
公共覆盖无效VisitMethodCall(方法调用)
{
方法CalledMethod=(call.Callee作为MemberBinding).BoundMember作为方法;
AddCallerOfMethod(CalledMethod,_CurrentMethod);
Queue MethodsToCheck=new Queue();
MethodsToCheck.Enqueue(称为method);
while(MethodsToCheck.Count!=0)
{
方法CurrentMethod=MethodsToCheck.Dequeue();
if(ChildTypes.ContainsKey(CurrentMethod.DeclaringType))
{
foreach(ChildTypes[CurrentMethod.DeclaringType]中的var-DerivedType)
{
var DerivedCalledMethod=DerivedType.Members.OfType()。其中(M=>MethodHidesMethod(M,CurrentMethod)).SingleOrDefault();
if(DerivedCalledMethod!=null)
{
AddCallerOfMethod(DerivedCalledMethod,CurrentMethod);
方法检查。排队(DerivedCalledMethod);
}
}
}
}
base.VisitMethodCall(调用);
}
私有void AddCallerOfMethod(方法CalledMethod,方法CallingMethod)
{
如果(!CallersOfMethod.ContainsKey(CalledMethod))
Add(CalledMethod,new List());
如果(!CallersOfMethod[CalledMethod].包含(CallingMethod))
CallersOfMethod[CalledMethod].Add(CallingMethod);
}
私有bool方法hidesmethod(方法ChildMethod、方法BaseMethod)
{
while(ChildMethod!=null)
{
if(ChildMethod==BaseMethod)
返回true;
ChildMethod=ChildMethod.OverridedMethod??ChildMethod.HiddenMethod;
}
返回false;
}
}

我不确定我是否真的理解您试图验证的内容。请您提供一个具体的代码示例,说明应该生成违反规则的代码。谢谢您的回答,但我不想在运行时或反射时执行此操作。我想用FxCop执行此操作,它执行静态检查,而不是运行时签入G
public class CallGraphBuilder : BinaryReadOnlyVisitor
{
    public Dictionary<TypeNode, List<TypeNode>> ChildTypes;

    public Dictionary<Method, List<Method>> CallersOfMethod;

    private Method _CurrentMethod;

    public CallGraphBuilder()
        : base()
    {
        CallersOfMethod = new Dictionary<Method, List<Method>>();
        ChildTypes = new Dictionary<TypeNode, List<TypeNode>>();
    }

    public override void VisitMethod(Method method)
    {
        _CurrentMethod = method;

        base.VisitMethod(method);
    }

    public void CreateTypesTree(AssemblyNode Assy)
    {
        foreach (var Type in Assy.Types)
        {
            if (Type.FullName != "System.Object")
            {
                TypeNode BaseType = Type.BaseType;

                if (BaseType != null && BaseType.FullName != "System.Object")
                {
                    if (!ChildTypes.ContainsKey(BaseType))
                        ChildTypes.Add(BaseType, new List<TypeNode>());

                    if (!ChildTypes[BaseType].Contains(Type))
                        ChildTypes[BaseType].Add(Type);
                }
            }
        }
    }

    public override void VisitMethodCall(MethodCall call)
    {
        Method CalledMethod = (call.Callee as MemberBinding).BoundMember as Method;

        AddCallerOfMethod(CalledMethod, _CurrentMethod);

        Queue<Method> MethodsToCheck = new Queue<Method>();

        MethodsToCheck.Enqueue(CalledMethod);

        while (MethodsToCheck.Count != 0)
        {
            Method CurrentMethod = MethodsToCheck.Dequeue();

            if (ChildTypes.ContainsKey(CurrentMethod.DeclaringType))
            {
                foreach (var DerivedType in ChildTypes[CurrentMethod.DeclaringType])
                {
                    var DerivedCalledMethod = DerivedType.Members.OfType<Method>().Where(M => MethodHidesMethod(M, CurrentMethod)).SingleOrDefault();

                    if (DerivedCalledMethod != null)
                    {
                        AddCallerOfMethod(DerivedCalledMethod, CurrentMethod);

                        MethodsToCheck.Enqueue(DerivedCalledMethod);
                    }
                }
            }
        }

        base.VisitMethodCall(call);
    }

    private void AddCallerOfMethod(Method CalledMethod, Method CallingMethod)
    {
        if (!CallersOfMethod.ContainsKey(CalledMethod))
            CallersOfMethod.Add(CalledMethod, new List<Method>());

        if (!CallersOfMethod[CalledMethod].Contains(CallingMethod))
            CallersOfMethod[CalledMethod].Add(CallingMethod);
    }

    private bool MethodHidesMethod(Method ChildMethod, Method BaseMethod)
    {
        while (ChildMethod != null)
        {
            if (ChildMethod == BaseMethod)
                return true;

            ChildMethod = ChildMethod.OverriddenMethod ?? ChildMethod.HiddenMethod;
        }

        return false;
    }
}