NDepend に少し苦労しています。説明するのは少し難しいです。コードベースにメソッドがあり (そのメソッドを「TheMethod」と呼びます)、特定の種類の他のメソッド (この種類を「TheKind」と呼びましょう) によって呼び出されてはなりませんが、何らかの属性 (「TheAttr」 )、直接的または間接的に; 間接的な場合、「TheAttr」で装飾されたホップは、間接的な使用法に違反することはありません。
「使用」を意味する「->」矢印、「[TheAttr]」を含む TheAttr を持つ前述の属性を持つメソッド、およびルールに違反する必要がある場合は「FAIL」という単語、違反する場合は「SUCCESS」という単語を使用して、いくつかのシナリオを視覚化します。規則に違反してはなりません。
そう...
「TheMethod」を直接的または間接的に使用して、「TheKind」のすべてのメソッドをトリガーする CQLinq クエリを作成できます。「TheAttr」を持つメソッドを結果から除外することもできます。
somemethod -> TheMethod FAIL
somemethod[TheAttr] -> TheMethod SUCCESS
間接的な用法をルールに組み込むのも簡単です。
somemethod -> method1 -> method2 -> TheMethod FAIL
somemethod[TheAttr] -> method1 -> method2 -> TheMethod SUCCESS
今、私が欲しいのはこれです:
somemethod -> method1[TheAttr] -> method2 -> TheMethod SUCCESS
と
somemethod -> method1 -> method2[TheAttr] -> TheMethod SUCCESS
したがって、言い換えれば、装飾を持つ中間呼び出し元は、「TheMethod」の有効な使用法をもたらす必要があります/有効な使用法を「介して」呼び出すことも有効である必要があります。
これは NDepend で確認できますか? 私は FillIterative を試しましたが、今のところ運がありません。
ありがとう、ティム
PS .:これが私の現在の試みです:
warnif count > 0
let mcalling = Methods.WithFullName("My.Namespace.MyType.get_SomeProperty()").SingleOrDefault().MethodsCallingMe.ToList()
let domain = mcalling.FillIterative(callers => // Unique loop, just to let a chance to build the hashset.
from o in (new object()).ToEnumerable()
let hashset = callers.ToHashSet() // Use a hashet to make Intersect calls much faster!
from m in Methods.UsingAny(callers).Except(callers)
where !m.HasAttribute("My.Namespace.NDependIgnore.MayUsePropAlthoughAsync".AllowNoMatch())
select m
)
let indirectcallers = domain.DefinitionDomain.Where(m1 => m1.IsAsync).ToArray() // Avoid double enumeration
from m in indirectcallers
let depth = m.DepthOfIsUsing("My.Namespace.MyType.get_SomeProperty()")
where depth >= 0
select new
{
Method=m,
Depth=depth,
Level=domain[m]
}