Integrate with IoC Framewoks
Parse IoC Framewoks settings XML files to append on-demand defined dependencies to the NDepend code model.
-
Alexander Yarushin commented
Absolutely MUST have this feature.
We have a 1.5 million LoC code-base and DI is what we use.
The usability of NDepend will increase dramatically if you will include implementation of interfaces in the analysis. Direct and Indirect dependencies differ only in the small part of the code where DI is hardly used. Other than that dependency chain breaks at interfaces.
This would still be Static Analysis because interface implementation is in the same code-base
-
It looks like NDepend supporting DI won't make it. We explain the reason for our decisions in this post:
https://blog.ndepend.com/static-analysis-and-dependency-injection/If you don't agree please let us know and comment. We are looking for productive discussions.
Thanks -
anton tishchenko commented
Let me explain more in details. Project is based on Sitecore.
There are Helix Architecture principles https://helix.sitecore.net/Following them: solution can consist from projects on different layers:
1) Foundation is core layer. It should be very stable and should not be changed often. Foundation projects could depend on each other
2) Feature is intermediate layer. It contains separate modules features that can work independently. Feature projects could depend on Foundation projects, but not on other features.
3) Projects is highest level. It should contain only specific code for website. It can depend on Features and Foundation projects. But could not depend on other Project.Following current NDepend report all is fine. All dependency principles are followed.
But, there is dependency of Foundation and Feature projects from Project in reality. Interface is declared in Foundation, but implementation is in Project and registered via DI. It means that Foundation projects, that are core and stable part of solution, depend on Project level, which is not so stable and reliable.
-
Hi Anton
>That is why I would love this feature, it will allow to understand real dependencies.
"Real dependencies" at runtime indeed,
>And sometime foundation level depends on project (in DI).
But why would this be a problem? I see here proper application of DIP Dependency Inversion Principle
- At design time Fundation depends on interfaces implemented by Project
- At design time of course Project depends on these interfaces since it contains classes that implement them
- At design time Fundation doesn't depend on Project
Why would it be a problem if at runtime Fundation depends on Project? (thanks to DI) -
anton tishchenko commented
Hi Patrick.
I think it will be very useful feature. We have layered architecture: foundation, feature, project.
Following current NDepend report, everything follows right dependencies. Project depends on feature and foundation. Feature depends on foundation. However due to some of DI registrations, we have complex dependencies. And sometime foundation level depends on project (in DI).That is why I would love this feature, it will allow to understand real dependencies.
We are using LightInject, however we not always using it in this way:
container.Register<IFoo, Foo>();We have wrapper under it, and major part of dependencies are registered by:
registry.Register<Interface, implementation>();
where registry is wrapper on container.So, my thoughts are that it would be nice, if dependency injection syntax to match would be configurable. (I understand that it adds complexity... And even without this configuration presence of this feature will be great)
-
We are planning to implement this within the next months. To clarify what we'd like to do suppose we have DI code like
container.RegisterType<ITab, HomeTab>();
container.RegisterType<ITab, GamesTab>();The idea will be that **all** usage of ITab or **all** call to ITag.Fct() will be seen also as an usage of HomeTab and GamesTab and a call to HomeTab.Fct()and GamesTab.Fct().
This will provoke some dependency cycles also an NDepend project setting will be proposed to disable this binding.
We'll investigate those frameworks: Autofac, UnityContainer, NInject, StructureMap, MEF, SimpleInjector, Castle.Windsor, LightInject, Prism, Spring.net
See below some sample syntax that we plan to support.We plan also the possibility to provide a .csv files with interface,class dependencies, for those using a custom DI fx. Thus for those using DI through custom XML file they'll need to transform the XML into the .csv format to use this feature.
Your feedback will be welcome
Some sample syntax that we plan to support:
Autofac
builder.RegisterType<EmailService>().As<IMailService>IUnityContainer
container.RegisterType<ICar, BMW>();NInject
Bind<IMailSender>().To<MockMailSender>();SimpleInjector
container.Register<IOrderRepository, SqlOrderRepository>();Castle.Windsor
container.Register(Component.For<ICompositionRoot>().ImplementedBy<CompositionRoot>());LightInject
container.Register<IFoo, Foo>();Prism
this.container.RegisterType<IOrdersRepository, OrdersRepository>(new ContainerControlledLifetimeManager());StructureMap
ObjectFactory.Initialize(x => { x.For<IStuff>().Use<RealStuff>(); });MEF
public interface ITab { void Fct() }
[Export(typeof(ITab))]
public class HomeTab : ITab { public void Fct() {} }
[Export(typeof(ITab))]
public class GamesTab : ITab { public void Fct() {}} -
Pressacco commented
Still waiting to see if this feature could add value to static analysis.
Re: our current project... all dependencies are being managed from within the code base using Unity.
-
Pressacco commented
This feature is long overdue.
-
Mark Kharitonov commented
Our DI is entirely in code, we do not have any XML.
Specifically, we use MEF for Dependency Injection. Everything is attribute based.
I agree, that in order to be meaningful the DI analysis should have deep knowledge of the respective DI framework.NDepend is unlikely to have a single implementation for all. It will probably have a modular implementation with a module per DI framework and ideally an API to allow third parties to develop modules for other DI frameworks. Something like that.
Non trivial, but essential if the call graph feature is to be supported in the future.
-
Mark Kharitonov commented
We are using MEF as our .NET Dependency Injection framework. But this would be true for any project considering itself as modern - a pervasive use of DI. NDepend is significantly less attractive as long as it does not support DI.
-
Anonymous commented
I would really love this feature, and also support for attribute based metadata clues for Classes. NDepend would be much better of understanding the implementation if I could somehow instruct with metadata attributes the IOC purpose and those implementations. I often see in some projects that have heavily using and abusing the IOC. The NDepend makes the whole dependency a very spaghetti, and sometimes the analysis is actually worse as it seems not accounting the IOC in analysis and diagrams.
-
Paul Saunders commented
Given that the general industry trend is away from xml configuration for IoC, this feature only really becomes useful when code IoC aware. As Dru said. It ain't going to be that easy.
-
Anonymous commented
Useless if it only looks at XML configuration
-
krainey commented
I agree with Steven that it would be more useful if NDepend could also look at DI container registration in code. I very seldom come across projects where configuration is done in XML -- it's virtually always done in code.
-
Dru Sellers commented
I would be very interested not in the XML parsing, but in tooling that is IoC aware. I don't expect that one to be easy or what it would really give me. but i like the idea.
-
Steven commented
That would not be a very useful features, since there should hardly be any of your DI configuration written in XML. 99% of the configuration should be done in code. So to do any useful analysis, NDepend should look at the code that configures the DI configuration, but this is actually very hard and to yield any useful analysis, this needs deep knowledge of the DI framework in question. For instance, just look at what the Agent Mulder (https://github.com/hmemcpy/AgentMulder) plug-in for Resharper does. It integrates DI containers with Resharper, but it stops at the point where DI containers get useful: batch registration. So to be honest, I don't think that static analysis is really helpful in this area, since DI containers dynamic in nature and you'll need to run code to be able to analyze what's happening.