I read a few things around on this site :
It is best to configure our container at the launch the application
It is best to avoid making our libraries dependent on a dependency injection framework
It is recommended to use factories to initialize objects whose properties are defined at the runtime
I use Ninject. If I understand these recommendations, it is necessary that:
My libraries do not use NInject.dll
Therefore, my NinjectModules must be defined in the project of my application
My factories (which are created on this principle) must also be defined in the project of my application, and not directly in the library
That seems strange, especially for factories. I have many projects that use the same library. Should all these projects redefine ninject modules and factories?
What do you think ?
The configuration does not necessarily be in the application assembly. It can also be in several dedicated assembly containing nothing than a part of the configuration. But as you mentioned it shouldn't be part of the implementation. In case you share exactly the same configuration over several projects you can reference an existing one.
For factories you can use Ninject.Extensions.Factory in the future so that you don't have to implement them yourself.
This depends a lot on the context of your libraries, how I do it is:
Initialize everything in a Bootstrapper in the main project. Although I have several levels of bootstrappers where I configure different things (mainly because I use my libraries in the same kind of projects, so they have similar configuration)
To keep this abstracted from the Ioc framework, I use the ServiceLocator pattern which you could use in your factories.
Related
We have a landscape with 15 solutions, where each solution contains many projects of its own. All solutions however, share some common project called "Model". Since each solution however, wires its own object graphs, this causes the registrations for the Model project to be duplicated 15 times.
What's the best way to prevent this duplication?
Example:
Solution-A
Model
public class Account
{
public Account()
{
var a=Resolve<IEmailer>();
}
}
The addition of above code in constructor forces me to register the dependencies in all start-up projects of the solutions if they refer the above class. Some solution need Account class but not IEmailer but still it need to inject IEmailer in that solution.
Registering everything in the start-up project is actually a good thing. This common place is called the Composition Root and it allows you to minimize the number of references between your projects, as explained clearly here.
Another thing you should prevent is letting your code (anything except your composition root) depend on the DI library or an abstraction over your DI library. So instead of calling Resolve from inside your constructors, let any dependency a class has be injected into the constructor of that class. Example:
public class Account
{
private readonly IEmailer emailer;
public Account(IEmailer emailer)
{
this.emailer = emailer;
}
}
This has many advantages over calling back into the container from within your code.
Do note though that your container is meant to build up object graphs of your services. If Account is an entity, resolving that from the container is not a usual and advised thing to do.
About the multiple-solution problem you're having: Since the shared project you're using, it might be good to prevent referencing this as a project, but make this an independent project with its own release cycle. Other projects can in that case depend on the assembly that you publish (for instance using your own local NuGet server).
But besides this, since this is a reusable project, make sure that assembly becomes a DI friendly library. If any bootstrapping should be done, and you want to prevent repeating this across solutions, create a separate bootstrapping-project. This bootstrapping-project refers to the reusable library and it references your Unity container. This way your library still stays completely independent to the used DI library, while you prevent duplicating bootstrapping logic throughout the solutions.
I am working on a library which needs to make use of the common service locator (http://commonservicelocator.codeplex.com/) to provide generic IOC support in order that we don't conflict with any consumers. Obviously I don't want to reference the IOC frameworks directly in my project but I'm unsure as to how to annotate the parts such that they can be found by the various frameworks. For instance MEF usually works by finding classes with the Export annotation and LinFu by finding classes with the Implements annotation. Both these annotations are defined within their respective projects requiring that I reference them both.
How can I get away from adding all these classes and annotating all my classes multiple times? It certainly doesn't adapt well to new IOC frameworks as a rebuild would be required for each new framework's annotations.
From the documentation:
"Libraries should not configure the
container"
"As a library or framework author,
understand that you should not be
putting anything into the container -
that's the job of your caller. Allow
the application writers to choose
whatever container they want. You need
to document what services you need
registered, and if you're using the
ServiceLocation.Current ambient
container."
So I don't think you need to export anything, just document what you need to consume in order to run. And optionally use the ServiceLocator.Current interface to resolve any dependencies you require.
Let's say I have a common WCF service and console app project that do not change across client specific deployments. I have some interfaces in the common projects that are implemented by specific client code. The client code obviously changes from client to client. I'm thinking this would be an appropriate use for an IoC container. In my common service projects, I drop the client specific dll in the bin and wire up the dependencies via IoC. The only trick is that this has to be done dynamically as the common service projects can't have a direct reference on a specific client project. Not a big deal though.
Is this correct usage of an IoC container?
If I understood correctly your system, maybe you can benefit from taking a look at the Managed Extensibility Framework.
Dependency Injection (DI - what you call IoC) is a slightly different beast than supporting Add-Ins/PlugIns.
The purpose of DI is to manage dependencies and decrease coupling between different parts of a system. It can feel a bit like Add-Ins, but is slightly different because you usually just replace one implementation of an interface with another.
With Add-Ins, on the other hand, the purpose is to provide zero, one, or many implementations of the same service.
In both cases you may want to resolve the implementations at run-time based on configuration files, scanning a folder or similar, so there's a great degree of overlap.
What makes it even more complicated is that Add-Ins may have depedencies in their own right, and you may want to support that (moving into DI territory).
For the Add-In scenario, I will second Konamimam's suggestion: MEF sounds like it would fit your requirements.
Yes, this will work fine. You just need to make sure the client specific DLLs bring along their own registration. With StructureMap, it would be implemented as Registry classes in the client specific DLLs.
I am currently writing an open source SDK for a program that I use and I'm using an IoC container internally(NInject) to wire up all my internal dependencies.
I have some objects that are marked as internal so that I don't crowd the public API as they are only used internally and shouldn't been seen by the user, stuff like factories and other objects. The problem that I'm having is that NInject can't create internal objects which means that I have to mark all my internal objects public which crowds up the public API.
My question is: Is there someway to get around this problem or am I doing it all wrong?
PS. I have thought about using InternalsVisiableTo attribute but I feel like that is a bit of a smell.
Quick look at the other answers: it doesn't seem like you are doing something so different that there is something fundamentally wrong with Ninject that you would need to modify it or replace it. In many cases, you can't "go straight for [the] internals" because they rely upon unresolved dependency injection; hence the usage of Ninject in the first place. Also it sounds like you already do have an internal set of interfaces which is why the question was posed.
Thoughts: one problem with using Ninject directly in your SDK or library is that then your users will have to use Ninject in their code. This probably isn't an issue for you because it is your IoC choice so you were going to use it anyway. What if they want to use another IoC container, then now they effectively have two running duplicating efforts. Worse yet what if they want to use Ninject v2 and you've used v1.5 then that really complicates the situation.
Best case: if you can refactor your classes such that they get everything they need through Dependency Injection then this is the cleanest because the library code doesn't need any IoC container. The app can wire up the dependencies and it just flows. This isn't always possible though, as sometimes the library classes need to create instances which have dependencies that you can't resolve through injection.
Suggestion: The CommonServiceLocator (and the Ninject adapter for it) were specifically designed for this situation (libraries with dependencies). You code against the CommonServiceLocator and then the application specifies which DI/IoC actually backs the interface.
It is a bit of a pain in that now you have to have Ninject and the CommonServiceLocator in your app, but the CommonServiceLocator is quite lightweight. Your SDK/library code only uses the CommonServiceLocator which is fairly clean.
I guess you don't even need that. IoC is for public stuff. Go straight for internals.
But - that's just my intuition...
Create a secondary, internal API which is different from the external API. You may need to do the split manually...
I'm going to vote for the InternalsVisibleTo solution. Totally not a smell, really. The point of the attribute is to enable the sort of behavior you are wanting, so rather than jumping through all sorts of elaborate hoops to make things work without it, just use the functionality provided by the framework for solving this particular problem.
I would also suggest, if you want to hide your choice of container from the user, using ILMerge to combine the Ninject assemblies with your SDK assembly, and apply the /internalize argument to change the visibility of the Ninject assemblies to internal, so the Ninject namespaces don't leak out of your library (sorry, couldn't find a link to the ILMerge docs online, but there is a doc file in the download). There is also this nice blog post about integrating ILMerge into your build process.
You can
modify Ninject
pick a different container
Say I have the following 4 .net assemblies:
Winforms UI
Business Logic
SQL Server Data Access (implementing an IRepository)
Common Interfaces (definition of IRepository etc.)
My business logic (2) makes calls to the data access layer (3) through IRepository (defined in 4) using constructor dependency injection. However when I ceate a business object I need to pass in an actual repository. I do this by having a singleton class in my business logic layer return the currently in use concrete object implementing IRepository. I am coming to the conclusion that this is a bad thing, as my business logic layer now has to reference 3 as well as 4.
I think I need a IoC Container but the question is where I create/put it as it seems that wherever I create this (1 - UI)? will also need to hold a reference to 3 (SQL Server Data Access). Am I not just moving the problem rather than achieving actual decoupling?
Do I create the IoC Container in the UI. Or expose it through another new assembly.
(I'm using C#, .net 3.5 and AutoFac)
Thanks.
IoC container generally should be created in the host project (application entry point). For the Windows.Forms application that's the exe project.
Generally in simple solutions (under 10 projects), only a host project should have a reference to IoC library.
PS: Structuring .NET Applications with Autofac IoC
When registering components there are several possibilities:
Registration in code:
directly
Problem: you have to reference everything ( you are here)
indirectly
Problem : to find out what has to be registered
Solution:
use attributes
use marker interface as IService
use conventions (see StructureMap)
Registration with configuration file:
let the container do everything
read the file yourself
Top level is a way to go (UI, as Rinat said).
Now as for references, simplest way is just to go over all assemblies in the current folder and use some convention to get the services out. Attributes work fine, putting registrar classes in each assembly works fine, whatever suits you. The code for extracting everything should probably be in a separate assembly, unless your IoC framework already does that.
The module distinction and the "scopes" defined by the modules exist mostly at compile-time. In the run-time it's all one big mess ;) This is used by most IOC containers and they don't really care about where they are located. The IoC container for a web-app will typically be created at the outermost level (very close to the web-container itself).
It's true that you could create it anywhere, but I'd introduce an extra layer, let's call it 3.5.
Your current 3 would be where your IoC resides for Data Access - this would become a wrapper for your actual DAL. Based on your config, 3 would create either a mock repository or a concrete one.
So 2 still references 3, but it's just an interface to the actual DAL which is configured through your IoC framework.
Alternatively, you could roll your own 'el-cheapo' IoC - change your Big Ugly Singleton to a Static Gateway - Abstracting IoC Container Behind a Singleton - Doing it wrong?