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?
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.
Related
Just started NDepend on a WPF project. Changed the "potentially dead types" built-in query to include our System.Windows.Application derived class instead of the class called Program:
// <Name>Potentially dead Types</Name>
warnif count > 0
let canTypeBeConsideredAsDeadProc = new Func<IType, bool>(
t => !t.IsPublic &&
(t.BaseClass == null || t.BaseClass.FullName != "System.Windows.Application") &&
!t.IsGeneratedByCompiler && ...
After tackling these, I would still need to deal with lots of dead methods found by NDepend that are actually used in a WPF Binding. Any ideas how to start on this without marking all such view-model properties with an attribute?
Unfortunately all methods used by only those properties also seem to be dead code, so this query "leaks" into parts of the model, too.
I'm implementing a variant of the JUnit New Test Suite Wizard, and instead of getting test classes from the current project, I need to get them from another source. They come to me as strings of fully-qualified class names.
Some of them may not yet exist in this user's workspace, let alone in the classpath of the current project. The user will need to import the projects for these later, but I don't want to mess with that in my wizard yet. I need to just add all classes to the new suite whether they exist yet or not.
For those classes that are already in this project's classpath, I can use IJavaProject.findType(String fullyQualifiedName) . Is there an analogous way to get ITypes for classes that are not (yet) visible?
I would be happy to construct an IType out of thin air, but ITypes don't seem to like being constructed.
I don't think that is possible: the Java Document Model interfaces are created based on the classpath.
Even worse, if the project do not exist in the users workspace, the resulting code would not compile, and that is another reason for not allowing the arbitrary creation of such constructs.
If I were you, I would try to help the user to import the non-existing projects in case of types are not available, thus avoiding the tackling with the Java Document Model.
For my purposes, creating a HypotheticalType and a HypotheticalMethod got the job done. I'm attaching an overview in case anyone else needs to follow this path.
First I created a HypotheticalType and had it implement the IType interface. I instantiated one of these at the proper spot in my modified wizard. Using Eclipse's Outline view I created a method breakpoint on all methods in my new class. This let me detect which methods were actually getting called during execution of my wizard. I also modified the constructor to take, as a String, the name of the class I needed the wizard to handle.
Almost all of the new methods are ignored in this exercise. I found that I could keep the default implementation (return null or return false in most cases) for all methods except the following:
the constructor
exists() - no modification needed
getAncestor(int) - no modification needed, but it might be useful to return the package of my hypothetical class, e.g. if my class is java.lang.Object.class, return java.lang.
getDeclaringType() - no modification needed
getElementName() - modified to return the class name, e.g. if my class is java.lang.Object.class, return Object.
getElementType() - modified to return IJavaElement.TYPE
getFlags() - not modified yet, but might be
getMethod(String, String[]) - modified to return a new HypotheticalMethod(name)
getMethods() - modified to return new IMethod[] { new HypotheticalMethod("dudMethod") }
In the process I discovered that I need to be able to return a HypotheticalMethod, so I created that type as well, inheriting from IMethod, and used the same techniques to determine which methods had to be implemented. These are the only methods that get called while this wizard runs:
The constructor - add a String parameter to bring in the name of the method
exists() - no modification needed
isMainMethod() - no modification needed
That covers the solution to my original question. Zoltán, I'll be doing as you suggested in an upcoming iteration and trying to assist the user in both the case in which the desired class is not yet in this project's classpath, and the case in which the desired class is in some project not yet in the workspace.
i have 2 concrete types "CategoryFilter" & "StopWordsFilter" that implements
"IWordTokensFilter".
Below is my setup:
ForRequestedType<IWordTokensFilter>().TheDefaultIsConcreteType<CategoryFilter>()
.AddInstances(x =>
{
x.OfConcreteType<StopWordsFilter>();
}
);
The problem is the run-time when structure map auto inject it on my class, bec. i have arguments with same plugin-type:
public ClassA(IWordTokensFilter stopWordsFilter, IWordTokensFilter categoryFilter)
i'm always getting CategoryFilter in my first argument but it should be stopWordsFilter.
How can i setup this in a right way? thanks in advance
There are a number of possible solutions:
1) Does ClassA need to differentiate between the filters, or does it just need to run them both? If not, you can change the constructor to accept an array, which will cause all registered instances of IWordTokensFilter to be injected:
public ClassA(IWordTokensFilter[] filters)
You can then foreach over the filters to apply them.
2) If you do need to differentiate them, because they need to be used differently, you may consider having one implement a marker interface the better describes its purpose. ClassA could then be changed to take in an IWordTokensFilter and an ICategoryFilter (or whatever you name the marker interface). Register CategoryFilter with ICategoryFilter and then both will be injected properly.
public ClassA(IWordTokensFilter stopWordsFilter, ICategoryFilter categoryFilter)
3) You can tell StructureMap explicitly how to create ClassA:
ForRequestedType<ClassA>().TheDefault.Is.ConstructedBy(c => {
return new ClassA(c.GetInstance<StopWordsFilter>(), c.GetInstance<CategoryFilter>());
});
4) You can tell StructureMap to override one of the dependencies for ClassA:
x.ForRequestedType<ClassA>().TheDefault.Is.OfConcreteType<ClassA>()
.CtorDependency<IWordTokensFilter>("stopWordsFilter").Is<StopWordsFilter>();
A fellow developer and I are conversing (to put it lightly) over Lazy-Loading of Properties of an object.
He says to use a static IoC lookup call for resolution and Lazy-Loading of objects of an object.
I say that violates SRP, and to use the owning Service to resolve that object.
So, how would you handle Lazy-Loading following IoC and SRP?
You cannot Unit test that lazy-loaded property. He rebuttles that one saying, "you already have unit tests for the UserStatsService - there's your code coverage." A valid point, but the property remains untested though for "complete" coverage.
Setup / code patterns:
Project is using strict Dependency Injection rules (injected in the ctors of all services, repositories, etc).
Project is using IoC by way of Castle (but could be anything, like Unity).
An example is below.
public class User
{
public Guid UserId { get; set; }
private UserStats _userStats;
// lazy-loading of an object on an object
public UserStats UserStats
{
get
{
if (_userStats == null)
{
// ComponentsLookup is just a wrapper around IoC
// Castle/Unity/etc.
_userStats =
ComponentsLookup
.Fetch<UserStatsService>()
.GetByUserId(this.UserId);
}
return _userStats;
}
}
}
The above shows an example of lazy-loading an object. I say not to use this, and to access UserStatsService from the UI layer wherever you need that object.
EDIT: One answer below reminded me of the NHibernate trick to lazy-loading, which is to virtualize your property, allowing NHibernate to create an over-load of the lazy-loading itself. Slick, yes, but we are not using NHibernate.
No one really tackles the matter of Lazy-Loading. Some good articles and SO questions get close:
Using Dependency Injection frameworks for classes with many dependencies
http://blog.vuscode.com/malovicn/archive/2009/10/16/inversion-of-control-single-responsibility-principle-and-nikola-s-laws-of-dependency-injection.aspx
I do see a benefit of lazy-loading. Don't get my wrong, all I did was lazy-loading of my complex types and their sub-types until I switched to the D.I.-ways of the ninja. The benefit is in the UI layer, where a user's stats is displayed, say, in a list with 100 rows. But with DI, now you have to reference a few lines of code to get that user stats (to not violate SRP and not violate the law-of-Demeter), and it has to walk this long path of lookups 100+ times.
Yes yes, adding caching and ensuring the UserStatsService is coded to be used as a Singleton pattern greatly lower the performance cost.
But I am wondering if anyone else out there has a [stubborn] developer that just won't bend to the IoC and D.I. rules completely, and has valid performance/coding points to justify the work-arounds.
Entities themselves should not have the responsibility of lazy loading. That is an infrastructural concern whose solution will lie elsewhere.
Let's say an entity is used in two separate contexts. In the first, its children are used heavily and are eagerly-loaded. In the second, they are used rarely and are lazy-loaded. Is that also the entity's concern? What would the configuration look like?
NHibernate answers these questions by proxying the entity type. A property of type IList<Entity> is set by the infrastructure to an implementation which knows about lazy loading. The entity remains blissfully unaware. Parent references (like in your question) are also handled, requiring only a simple property.
Now that the concern is outside the entity, the infrastructure (ORM) is responsible for determining context and configuration (like eager/lazy loading).
When Instantiating a class, Windsor by default treats all public properties of the class as optional dependencies and tries to satisfy them. In my case, this creates a rather complicated circular dependency which causes my application to hang.
How can I explicitly tell Castle Windsor that it should not be trying to satisfy a public property? I assume there must be an attribute to that extent. I can't find it however so please let me know the appropriate namespace/assembly.
If there is any way to do this without attributes (such as Xml Configuration or configuration via code) that would be preferable since the specific library where this is happening has to date not needed a dependency on castle.
You can use the Castle.Core.DoNotWireAttribute attribute to stop a property from being wired up by the IoC container (this is in the Castle.Core assembly, which means your library only needs to take a dependency on the lightweight Castle.Core assembly - if for example you want to use the code without an inversion of control container altogether, or in a different IoC container).
I don't believe there's any way to prevent wiring from occurring in the Xml configuration, but it would be reasonably easy to add support for this - if I had to do this I would probably:
Introduce some kind of attribute on the property declaration in the xml: <myprop wire="false" />
Inherit from PropertiesDependenciesModelInspector, overriding the InspectProperties method to apply some additional logic to identifying which properties should be added as dependencies to the components model (inspecting the model.Configuration for the wire="false" attribute/value pair).
Inherit from DefaultComponentModelBuilder and override the InitializeContributors to include your replacement PropertiesDependenciesModelInspector - or just remove the existing properties contributor and add your own at run time via the AddContributor/RemoveContributor methods.
Replace the ComponentModelBuilder service instance assigned to the kernel of your container.
Another approach which could work for you is to just manually remove the dependencies from the model before any instances of the service are requested ie.
kernel.GetHandler(typeof(MyComponent)).ComponentModel.Dependencies.RemoveAll(d => d.DependencyKey == "PropertyThatShouldNotBeWired");
YMMV with that approach though - especially if you have startable services or other facilities which may be eagerly instantiating your component after it's registered.
I created a facility to help with this:
Castle.Facilities.OptionalPropertyInjection
I do not know which version of Castle you guys were using at that time, but none of the solution mentioned were working. Plus, there is a lot of dead links.
With castle 3.1, here the solution I came up with (thanks to some castle source code digging):
container.Register(Component.For(type)
.LifestyleTransient()
.Properties( propertyInfo => propertyInfo.PropertyType != typeof(MyOtherType)));
The 'Properties' function adds a property filter used by castle when constructing the ComponentModel. In my case, all properties dependency will be satisfied except the property type 'MyOtherType'.
Maybe it will be helpful for someone. In Windsor 4.1 there is PropertiesIgnore method during registration.
Component.For<Role>().LifestyleTransient().PropertiesIgnore((model, propertyInfo) => true)
DoNotWireAttribute
Class: http://svn.castleproject.org:8080/svn/castle/trunk/Core/Castle.Core/Attributes/DoNotWireAttribute.cs
Test: http://svn.castleproject.org:8080/svn/castle/trunk/InversionOfControl/Castle.Windsor.Tests/IgnoreWireTestCase.cs
This can be achieved by the following code:
var container = new WindsorContainer();
// We don't want to inject properties, only ctors
var propInjector = container.Kernel.ComponentModelBuilder
.Contributors
.OfType<PropertiesDependenciesModelInspector>()
.Single();
container.Kernel.ComponentModelBuilder.RemoveContributor(propInjector);
Source Castle Windsor Documentation
Posted this on the google groups forum too here: http://groups.google.com/group/castle-project-devel/browse_thread/thread/43aa513817bd057a