2011-06-22 10 views
8

Belirli bir öznitelikle işaretlenmiş bir yöntemle çağrılan herhangi bir yöntemde nesne ayırma gerçekleştirilirse başarısız olacak bir kural yazmak istiyorum.Bir yöntemin yeni bir deyim içeren ve başka bir deyimde bir yöntem çağırıp çağıracağını belirleme

Şu ana kadar, bu ana yöntemlerden herhangi birinin özniteliği olup olmadığını görmek için yöntemimi çağıran tüm yöntemleri yineleyerek, CallGraph.CallersFor() kullanarak denetleme yöntemini tamamladım.

Bu, ana makine yöntemlerini denetlenecek yöntemle aynı derlemede denetlemek için çalışır, ancak çevrimiçi olarak okunduğunda, bir kerede CallGraph.CallersFor() tüm derlemelere bakmış görünüyor, ancak şimdi değil.

Soru: Farklı bir gruptakiler de dahil olmak üzere belirli bir yöntemi çağıran yöntemlerin bir listesini almanın bir yolu var mı?

Alternatif Yanıt: Yukarıdakiler mümkün değilse, farklı bir derlemede olanlar da dahil olmak üzere belirli bir yöntem tarafından çağrılan her yönteme nasıl bağlanırım?


Örnek:

-----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(); 
    } 
} 

kural hatası yeterlidir alma bu aşamada, hata bildirir nerede gerçekten umursamıyorum.

+0

ben gerçekten doğrulamak için çalışıyoruz anlamak emin değilim. kod somut bir örnek verebilir misiniz olduğunu should kural ihlali oluşturulsun? –

+0

@Nicole: Ed ited. –

cevap

2

benim FxCop projedeki tüm başvurulan DLL ekleme ve elle çağrı ağacı oluşturur aşağıdaki kodu kullanarak bu konuda yuvarlak var, bu şekilde bir deneyin vermek mü (o Ayrıca türetilmiş sınıflar için çağrılar i karşılaşılan başka bir sorun yuvarlak here çalışmak ekler.

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; 
    } 
} 
0

Eğer

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

Cevabınız için teşekkürler, ancak bunu çalışma zamanında veya yansımayla yapmaya çalışmıyorum. Çalışma zamanı kontrolü yerine statik kontrol yapan FxCop ile bu kuralı yapmaya çalışıyorum. –

İlgili konular