Pregunta

My NDepend reports warn that 'Non-static classes should be instantiated or turned to static.' Most of the classes in the returned list are registered via my IOC container (Unity) and instantiated by my IOC framework at runtime.

Given that NDepend is performing static analysis, it's not going to be aware of the runtime instantiation. I'm hoping that it's possible to tweak the CQL to make it aware of my container.

This is the boilerplate query that NDepend executes:

warnif count > 0
from t in JustMyCode.Types
where  t.IsClass &&
//!t.IsPublic &&   // if you are developping a framework, 
                   // you might not want to match public classes
  !t.IsStatic && 
  !t.IsAttributeClass && // Attributes class are never seen as instantiated
  !t.DeriveFrom("System.MarshalByRefObject".AllowNoMatch()) // Types instantiated through remoting infrstructure

// find the first constructor of t called
let ctorCalled = t.Constructors.FirstOrDefault(ctor => ctor.NbMethodsCallingMe > 0)

// match t if none of its constructors is called.
where ctorCalled == null
select new { t, t.Visibility }

Is it possible for me to tweak this query to exclude classes that are referenced in my IOC container registration?

¿Fue útil?

Solución

Indeed, you can vote for NDepend supports of IoC Framework on the NDepend User Voices site. This is a feature that will be implemented in the future.


For now, you can handle this with an attribute. Create an attribute class in your code, for example named MyProduct.IoCInstantiatedAttribute.

Then you can tag all your classes instantiated solely by IoC with this attribute. Since this attribute is only needed on DEBUG build (the one analyzed by NDepend) I'd advice using a conditional DEBUG syntax.

#if DEBUG
[IoCInstantiated]
#endif
class MyClass { ... }

Finally, you just have to add && !t.HasAttribute("MyProduct.IoCInstantiatedAttribute") in your concerned rule(s) et voilà!

Additionally, you can also write a rule to make sure that classes that have this attribute are not instantiated somewhere. This way you'll keep the usage of this attribute clean!

// <Name>Types tagged with attribute IoCInstantiated must not be instantiated elsewhere</Name>
warnif count > 0 
from t in Types 
where t.HasAttribute ("MyProduct.IoCInstantiatedAttribute") 
let methodsInstiatingMe = Application.Methods.ThatCreateA(t)
where methodsInstiatingMe.Any()
select new { t, methodsInstiatingMe }

Personally I found that using such attribute is great, because it also documents code. When a developer is reviewing such class, he can have this important piece of information (instantiated solely through IoC) at a glance.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top