Making dependency injection optional by introducting a factory? - c#

So I have a piece of software containing a brunch of service classes. Those services take some dependencies though their respective constructors.
I have designed with dependency injection in mind, but developers who are going to build on top of the software, may not want to use DI. Therefore I have not implemented an IOC container, so it is up to the developer to introduce one if desired.
My problem is that the software comes with an administration website, which uses these services.
I don't want to hardcode the service dependencies in the site, because I want to make it possible for the developers to switch them if they want to.
So how should I go about this?
I was thinking about introducing a factory for services, and give it a fixed static location somewhere. Then use it on the site.
public class ServiceFactory : IServiceFactory
{
public static IServiceFactory Current { get; set; }
static ServiceFactory()
{
Current = new ServiceFactory();
}
public TService Create<TService>()
{
// Creation logic here.
}
}
Developers will be able to control things by setting their own implementation of IServiceFactory to the static ServiceFactory.Current property.
Is this the way to go?

Two things I would like to note.
What you are proposing is not Dependency Injection, rather Service Location. They are not the same.
Ideally dependency injection is fully transparent to a developer. I.e. the true dependencies enter through the constructor and not via an indirection.

Have you looked into the CommonServiceLocator library? It is designed to provide an abstraction layer over an IOC container, however you could equally use it to abstract a service factory as you describe, that way your application would be able to resolve its dependencies without necessarily knowing whether they were coming from DI or a factory implementation...

Related

Can constructor initialization be used for dependency injection instead of having DI containers?

here's an example of what i am talking about
public interface IService<T>
where T : class
{
List<T> GetAll();
T GetById(object id);
.......... other methods here
}
public class Service<T> : IService<T>
where T : class
{
... implement interface here
}
public class ServiceClient
{
private readonly IService<User> _service;
public ServiceClient(IService<User> service)
{
_service = service;
}
public ServiceClient() : this(new Service<User>()){}
}
can someone tell me the difference between this and a Dependency Resolver? I normally Use SimpleInjector for Dependency Injection, I just want to know the benefits of the Container over doing the above..
Thanks
Update
okay lets say I have setup my Containers now and removed the 'this' constructor initialization, I Want to now Test ServiceClient
Let use MS unit test for snippet
[TestMethod]
public void Given_Something_Should_Success()
{
// Arrange
// how do i make an instance of this in a test without adding the 'new Service<User>()' part
ServiceClient client = new ServiceClient(new Service<User>());
}
and without changing my ServiceClient constructor to do this. Is it even possible to do that at this level? Sorry if this is a noob question i'm just trying to understand some things about it.
public ServiceClient(IService<User> service = null)
{
_service = service ?? new Service<User>();
}
See this line of code:
public ServiceClient() : this(new Service<User>()){}
Now the ServiceClient is aware of Service<User> class and the assembly where the ServiceClient is will not build without having a reference to the assembly where Service<User> class is located. Furthermore, if Service<User> has additional methods which are not in IServiceUser<User>, then the developer may do this within the class:
(this._service as Service<User>).SomeMethodNotBelongingToTheInterface();
Now one can argue that an irresponsible developer will do that sort of thing, but that is beyond the point here.
To be totally decoupled from the concrete implementations, you should never call new and leave this to the Composition Root. Both your classes and your assembly should only work with the interfaces and be totally unaware of the concrete implementations. This guarantees that you can plug any implementation at the composition root level, and everything will work.
This does not mean that even POCO classes without behavior should be behind interfaces but just classes that require plug and play sort of behavior.
If you follow this pattern, you can also create architectural diagrams within Visual Studio and instruct which layer can have references to which assemblies. During build, the build will fail (if configured to fail) if the developer creates a reference to an assembly they are not allowed to reference.
At the composition root level, it is up to you whether you want to plug the classes into each other using an IoC container or doing it manually. But why do it manually if there are good tools (IoC containers) which can do this for you. You can have one config file where all the test classes are and another where the real classes are. You can instruct your whole program to run with either configuration with just one line of code: This is what I mean by plug and play. The whole idea behind dependency injection, loose coupling etc. is that your classes should not have code which is written against a concrete implementation.
In Container you would register your class and interface.
Benefits are , you have one ioc class which will take care of providing you right type.
So you can program against interface.
and you do not need to new up in your code.
this gives you also flexibility when you have to manage scope or mock some class.
Here is some example how you register via IoC (Autofac)
builder.RegisterInstance(new ServiceClient())
.As<IService>();
What using a Container gives you is a centralised place in your application to specify how your dependencies should be resolved.
Imagine you have many classes that wants to inject the same implementation of IService. By using your approach above, you would have to write that same code for all of those classes. If you would have used a container, specifying it there would be enough.
Also, many DIs gives you more functionality for sharing instances, maintaining life cycles of your injections etc, provide dependencies to your dependencies etc.
This is called Bastard injection and you shouldn't do this because is totally against the purpose of dependency inversion: to create decoupled and maintainable code. If you use a default implementation it means that you have to reference the project that contains the implementation of your service. Or worst you probably create the implementation of your service in the same library where it lives the interface.
On the other hand you might have a good default implementation. For example you might define this interface:
public interface IClock
{
DateTime Now { get; }
}
The obvious implementation of this interface is
public class Clock : IClock
{
public DateTime Now => DateTime.Now;
}
I wouldn't use though a public constructor for this, I would inject it via a Property and leave the constructor for another implementation (maybe a mock from your tests). Also SimpleInjector I think would shout about having two constructors. It is a tool which made me to read more about these ideas.
When the IService's implementation is something that talks with a database, or HTTP service, or a remote one, or with 3rd party library or with file system, then these are good reasons for you create a separate project, reference the one you defined the interface, create the implementation, then in your place where you setup the simple injector, you can bind the interface with the implementation (which requires here to reference both projects). If on a later time you need a diferent implementation you can simply repeat the process and change the composition root.

DI in class library [duplicate]

I'm pondering the design of a C# library, that will have several different high level functions. Of course, those high-level functions will be implemented using the SOLID class design principles as much as possible. As such, there will probably be classes intended for consumers to use directly on a regular basis, and "support classes" that are dependencies of those more common "end user" classes.
The question is, what is the best way to design the library so it is:
DI Agnostic - Although adding basic "support" for one or two of the common DI libraries (StructureMap, Ninject, etc) seems reasonable, I want consumers to be able to use the library with any DI framework.
Non-DI usable - If a consumer of the library is using no DI, the library should still be as easy to use as possible, reducing the amount of work a user has to do to create all these "unimportant" dependencies just to get to the "real" classes they want to use.
My current thinking is to provide a few "DI registration modules" for the common DI libraries (e.g a StructureMap registry, a Ninject module), and a set or Factory classes that are non-DI and contain the coupling to those few factories.
Thoughts?
This is actually simple to do once you understand that DI is about patterns and principles, not technology.
To design the API in a DI Container-agnostic way, follow these general principles:
Program to an interface, not an implementation
This principle is actually a quote (from memory though) from Design Patterns, but it should always be your real goal. DI is just a means to achieve that end.
Apply the Hollywood Principle
The Hollywood Principle in DI terms says: Don't call the DI Container, it'll call you.
Never directly ask for a dependency by calling a container from within your code. Ask for it implicitly by using Constructor Injection.
Use Constructor Injection
When you need a dependency, ask for it statically through the constructor:
public class Service : IService
{
private readonly ISomeDependency dep;
public Service(ISomeDependency dep)
{
if (dep == null)
{
throw new ArgumentNullException("dep");
}
this.dep = dep;
}
public ISomeDependency Dependency
{
get { return this.dep; }
}
}
Notice how the Service class guarantees its invariants. Once an instance is created, the dependency is guaranteed to be available because of the combination of the Guard Clause and the readonly keyword.
Use Abstract Factory if you need a short-lived object
Dependencies injected with Constructor Injection tend to be long-lived, but sometimes you need a short-lived object, or to construct the dependency based on a value known only at run-time.
See this for more information.
Compose only at the Last Responsible Moment
Keep objects decoupled until the very end. Normally, you can wait and wire everything up in the application's entry point. This is called the Composition Root.
More details here:
Where should I do Injection with Ninject 2+ (and how do I arrange my Modules?)
Design - Where should objects be registered when using Windsor
Simplify using a Facade
If you feel that the resulting API becomes too complex for novice users, you can always provide a few Facade classes that encapsulate common dependency combinations.
To provide a flexible Facade with a high degree of discoverability, you could consider providing Fluent Builders. Something like this:
public class MyFacade
{
private IMyDependency dep;
public MyFacade()
{
this.dep = new DefaultDependency();
}
public MyFacade WithDependency(IMyDependency dependency)
{
this.dep = dependency;
return this;
}
public Foo CreateFoo()
{
return new Foo(this.dep);
}
}
This would allow a user to create a default Foo by writing
var foo = new MyFacade().CreateFoo();
It would, however, be very discoverable that it's possible to supply a custom dependency, and you could write
var foo = new MyFacade().WithDependency(new CustomDependency()).CreateFoo();
If you imagine that the MyFacade class encapsulates a lot of different dependencies, I hope it's clear how it would provide proper defaults while still making extensibility discoverable.
FWIW, long after writing this answer, I expanded upon the concepts herein and wrote a longer blog post about DI-Friendly Libraries, and a companion post about DI-Friendly Frameworks.
The term "dependency injection" doesn't specifically have anything to do with an IoC container at all, even though you tend to see them mentioned together. It simply means that instead of writing your code like this:
public class Service
{
public Service()
{
}
public void DoSomething()
{
SqlConnection connection = new SqlConnection("some connection string");
WindowsIdentity identity = WindowsIdentity.GetCurrent();
// Do something with connection and identity variables
}
}
You write it like this:
public class Service
{
public Service(IDbConnection connection, IIdentity identity)
{
this.Connection = connection;
this.Identity = identity;
}
public void DoSomething()
{
// Do something with Connection and Identity properties
}
protected IDbConnection Connection { get; private set; }
protected IIdentity Identity { get; private set; }
}
That is, you do two things when you write your code:
Rely on interfaces instead of classes whenever you think that the implementation might need to be changed;
Instead of creating instances of these interfaces inside a class, pass them as constructor arguments (alternatively, they could be assigned to public properties; the former is constructor injection, the latter is property injection).
None of this presupposes the existence of any DI library, and it doesn't really make the code any more difficult to write without one.
If you're looking for an example of this, look no further than the .NET Framework itself:
List<T> implements IList<T>. If you design your class to use IList<T> (or IEnumerable<T>), you can take advantage of concepts like lazy-loading, as Linq to SQL, Linq to Entities, and NHibernate all do behind the scenes, usually through property injection. Some framework classes actually accept an IList<T> as a constructor argument, such as BindingList<T>, which is used for several data binding features.
Linq to SQL and EF are built entirely around the IDbConnection and related interfaces, which can be passed in via the public constructors. You don't need to use them, though; the default constructors work just fine with a connection string sitting in a configuration file somewhere.
If you ever work on WinForms components you deal with "services", like INameCreationService or IExtenderProviderService. You don't even really know what what the concrete classes are. .NET actually has its own IoC container, IContainer, which gets used for this, and the Component class has a GetService method which is the actual service locator. Of course, nothing prevents you from using any or all of these interfaces without the IContainer or that particular locator. The services themselves are only loosely-coupled with the container.
Contracts in WCF are built entirely around interfaces. The actual concrete service class is usually referenced by name in a configuration file, which is essentially DI. Many people don't realize this but it is entirely possible to swap out this configuration system with another IoC container. Perhaps more interestingly, the service behaviors are all instances of IServiceBehavior which can be added later. Again, you could easily wire this into an IoC container and have it pick the relevant behaviors, but the feature is completely usable without one.
And so on and so forth. You'll find DI all over the place in .NET, it's just that normally it's done so seamlessly that you don't even think of it as DI.
If you want to design your DI-enabled library for maximum usability then the best suggestion is probably to supply your own default IoC implementation using a lightweight container. IContainer is a great choice for this because it's a part of the .NET Framework itself.
EDIT 2015: time has passed, I realize now that this whole thing was a huge mistake. IoC containers are terrible and DI is a very poor way to deal with side effects. Effectively, all of the answers here (and the question itself) are to be avoided. Simply be aware of side effects, separate them from pure code, and everything else either falls into place or is irrelevant and unnecessary complexity.
Original answer follows:
I had to face this same decision while developing SolrNet. I started with the goal of being DI-friendly and container-agnostic, but as I added more and more internal components, the internal factories quickly became unmanageable and the resulting library was inflexible.
I ended up writing my own very simple embedded IoC container while also providing a Windsor facility and a Ninject module. Integrating the library with other containers is just a matter of properly wiring the components, so I could easily integrate it with Autofac, Unity, StructureMap, whatever.
The downside of this is that I lost the ability to just new up the service. I also took a dependency on CommonServiceLocator which I could have avoided (I might refactor it out in the future) to make the embedded container easier to implement.
More details in this blog post.
MassTransit seems to rely on something similar. It has an IObjectBuilder interface which is really CommonServiceLocator's IServiceLocator with a couple more methods, then it implements this for each container, i.e. NinjectObjectBuilder and a regular module/facility, i.e. MassTransitModule. Then it relies on IObjectBuilder to instantiate what it needs. This is a valid approach of course, but personally I don't like it very much since it's actually passing around the container too much, using it as a service locator.
MonoRail implements its own container as well, which implements good old IServiceProvider. This container is used throughout this framework through an interface that exposes well-known services. To get the concrete container, it has a built-in service provider locator. The Windsor facility points this service provider locator to Windsor, making it the selected service provider.
Bottom line: there is no perfect solution. As with any design decision, this issue demands a balance between flexibility, maintainability and convenience.
What I would do is design my library in a DI container agnostic way to limit the dependency on the container as much as possible. This allows to swap out on DI container for another if need be.
Then expose the layer above the DI logic to the users of the library so that they can use whatever framework you chose through your interface. This way they can still use DI functionality that you exposed and they are free to use any other framework for their own purposes.
Allowing the users of the library to plug their own DI framework seems a bit wrong to me as it dramatically increases amount of maintenance. This also then becomes more of a plugin environment than straight DI.

What is a good strategy for initializing an IoC container within a class library?

I'm writing a class library (in C#) that will be distributed with applications I have no control over. My library is also a little bit security sensitive and thus I do not want to allow the calling app to do any configuration of the dependencies for the class library. It must be self-contained and initialize its own dependencies.
At the same time, I want it to be unit-testable and loosely coupled and I want to use an IoC container to manage the dependencies. At the moment I'm using internal constructors and [InternalsVisibleTo()] so that the unit tests can do manual injection. I prefer to use Ninject as my IoC container but that's sort of irrelevant to the question, I think.
I'm struggling to come up with a good strategy for initializing my IoC container in production, since the class library doesn't really have a defined entry point, it has a number of classes that can be instantiated with no way of knowing which one the app will use first.
I wondered if there may be some sort of AssemblyLoad event, and indeed the AppDomain seems to have such an event, but my assembly must already have been loaded into the AppDomain before I can even hook into that, so I would always miss the event raised by my own assembly being loaded. I also thought about using a static initializer or constructor, but I'm not really happy to pollute every possible class with IoC container setup because that makes them tightly coupled to the container. I don't want to decouple my code only to then couple it to the IoC container.
I have found a few other questions discussing this topic but none of them really deals with my situation. One suggested using a static initializer, another suggested that the application should always be the composition root.
Is there another way?
There is a contradiction between your requirements.
First, you don't want the Composition Root because of the security concern. Second, you want dependencies to be resolved by a container. But since the library doesn't control the container, pretty much anything can be injected into your code, including stuff that would try to break anything from inside.
One approach would be to have your dependencies explicit so that library clients are responsible for feeding your dependencies.
namespace Library
{
public class Foo1
{
// a classical IoC dependendency
public Foo1( IBar bar )
{
}
}
}
On the other hand, using a Composition Root which is an explicit external point of initializing your library still doesn't mean your library is polluted. CR works great with a Local Factory (aka the Dependency Resolver) which is responsible for internal object creation and it is set up from within the CR.
namespace Library
{
public interface IFoo { }
// local Foo factory, with a customizable provider
public class FooFactory
{
private static Func<IFoo> _provider;
public static void SetProvider( Func<IFoo> provider )
{
_provider = provider;
}
public IFoo CreateFoo()
{
return _provider();
}
}
// Bar needs Foo
public class Bar
{
public void Something()
{
// you can use the factory here safely
// but the actual provider is configured elsewhere
FooFactory factory = new FooFactory();
IFoo foo = factory.CreateFoo();
}
}
}
and then somewhere in the Composition Root (close to application's entry point)
// kernel is set up to map IFoo to an implementation of your choice
public void ComposeRoot( IKernel kernel )
{
FooFactory.SetProvider( () => kernel.Get<IFoo>() );
}
As you can see, instead of possibly providing multiple injection points in multiple classes, the Local Factory is a single injection point that provides a clean configuration of the whole library making it self-contained.
You could even have a provider that doesn't involve any IoC container but rather create a concrete implementation, thus making it easily testable without any container. Switching to another IoC is straightforward, you just provide another provider.
The larger your library is and your classes are cohesive (use each other often), the more convenient is to have a Local Factory. You don't need to rethrow dependencies between your classes (without a Local Factory, if your class A needs I and your B needs A then automatically B needs I), rather, all your classes depend on a single factory.
There are two scenarios here:
A) Your consumers aren't using your Ninject container:
If you don't want them to be able to provide alternate configurations (or are injecting internal classes), you must create a constructor that will resolve these dependencies yourself. This will be your point of entry.
B) You consumers are using your Ninject container:
You will need to expose your Ninject kernel instance to your consumers. This can either be wrapped in a ServiceLocator if you want to hide the fact that you are using Ninject, or by simply exposing the kernel itself. In either case, you can make it a property on a static class which will be your entry point.
From an internal standpoint, I prefer using option B, but as a frequent consumer of 3rd party libraries, I have never seen anyone expose their IoC container, not would I ever want them to. I just want to be able to instantiate a class, and not worry about any internal implementation or dependencies. You milage may vary, of course.

Pass parameter from a ViewModel to another with IoC

I'm trying to instantiate a SecondViewModel from a MainViewModel injecting in this second one paramaters that are services registered in the IoCContainer and objects from the MainVM.
The code is something of this kind:
class MainViewModel
{
public MainViewModel()
{
}
private string message = "the message";
public string Message { get; set; }
}
class SecondViewModel
{
public SecondViewModel(IService service, string message)
{
}
}
now, i know i can make the IoC Container inject a SecondViewModelFactory (that carries the service instance) into the MainViewModel, so it can create the SVM through it, but what if the implementation of IService is very heavy and i don't want to instantiate it but when i really need it.
And what if i have to instantiate other ViewModels in a similar way? Do I have to create tons of VMFactories and constructor's parameters?
And in case I use a generic ViewModelFactory, it would need to be instantiated passing all the services needed by every ViewModel I have, regardless if they will be created or not.
Do you know any better solution to my case?
In general, the creation of services should not be heavy. Their constructor should do nothing more than storing the incoming dependencies. If it uses some heavy resources in the background, they shouldn't be accessed through the constructor. This keeps the constructor simple (prevents you from having to test it) and allows the object graph to be composed very rapidly.
If there is really no way around this, there are basically two patterns you can apply:
1. Factories
You can inject a factory to delay the creation of a type. Factories are also useful when objects are created that should be controlled explicitly (for instance, instances that should be disposed as soon as possible). There are several ways of creating factories. Some people like to inject Func<T> or Lazy<T> dependencies into their services, but I find this too implicit. I rather inject an ISomeServiceFactory, since I find this more readable. Downside is that you need to define a new interface for this. However, if you find yourself having many factory interfaces, you probably have a problem in your design anyway.
2. Proxies
Instead of creating a factory, you can hide the service behind a proxy. This proxy can implement the same interface as the service and will do the delayed execution for you. This prevents you from letting the application take a dependency on a different interface (an IServiceFactory or Lazy<T> for instance). Especially Lazy<T> leaks details about the creation into the consumer of such a dependency. You can still inject a Lazy<T> into this proxy, if that's convenient. That's not a problem. That proxy would typically be part of your composition root and the rest of your application would still be dependend on your IService and not your Lazy<IService>.
Please be aware that the use of factories, proxies and lazy initiation does complicate the wiring of the container. So don't use if unless you measured that you really need it. They complicate things, because of the indirection, which makes it harder to follow interlectually. And they make it harder to verify your configuration using automated tests. For more information about verifying your container, take a look here and here.
Most IoC Containers supports Lazy dependency to with Lazy<> to avoid creating expensive class immediately.
So in your code, you can make lazy for your expensive IService:
class SecondViewModel
{
public SecondViewModel(Lazy<IService> service, string message)
{
}
}
You can use some popular IoC Containers and see how they support lazy loading: Autofac or NInject

Dependency Inject (DI) "friendly" library

I'm pondering the design of a C# library, that will have several different high level functions. Of course, those high-level functions will be implemented using the SOLID class design principles as much as possible. As such, there will probably be classes intended for consumers to use directly on a regular basis, and "support classes" that are dependencies of those more common "end user" classes.
The question is, what is the best way to design the library so it is:
DI Agnostic - Although adding basic "support" for one or two of the common DI libraries (StructureMap, Ninject, etc) seems reasonable, I want consumers to be able to use the library with any DI framework.
Non-DI usable - If a consumer of the library is using no DI, the library should still be as easy to use as possible, reducing the amount of work a user has to do to create all these "unimportant" dependencies just to get to the "real" classes they want to use.
My current thinking is to provide a few "DI registration modules" for the common DI libraries (e.g a StructureMap registry, a Ninject module), and a set or Factory classes that are non-DI and contain the coupling to those few factories.
Thoughts?
This is actually simple to do once you understand that DI is about patterns and principles, not technology.
To design the API in a DI Container-agnostic way, follow these general principles:
Program to an interface, not an implementation
This principle is actually a quote (from memory though) from Design Patterns, but it should always be your real goal. DI is just a means to achieve that end.
Apply the Hollywood Principle
The Hollywood Principle in DI terms says: Don't call the DI Container, it'll call you.
Never directly ask for a dependency by calling a container from within your code. Ask for it implicitly by using Constructor Injection.
Use Constructor Injection
When you need a dependency, ask for it statically through the constructor:
public class Service : IService
{
private readonly ISomeDependency dep;
public Service(ISomeDependency dep)
{
if (dep == null)
{
throw new ArgumentNullException("dep");
}
this.dep = dep;
}
public ISomeDependency Dependency
{
get { return this.dep; }
}
}
Notice how the Service class guarantees its invariants. Once an instance is created, the dependency is guaranteed to be available because of the combination of the Guard Clause and the readonly keyword.
Use Abstract Factory if you need a short-lived object
Dependencies injected with Constructor Injection tend to be long-lived, but sometimes you need a short-lived object, or to construct the dependency based on a value known only at run-time.
See this for more information.
Compose only at the Last Responsible Moment
Keep objects decoupled until the very end. Normally, you can wait and wire everything up in the application's entry point. This is called the Composition Root.
More details here:
Where should I do Injection with Ninject 2+ (and how do I arrange my Modules?)
Design - Where should objects be registered when using Windsor
Simplify using a Facade
If you feel that the resulting API becomes too complex for novice users, you can always provide a few Facade classes that encapsulate common dependency combinations.
To provide a flexible Facade with a high degree of discoverability, you could consider providing Fluent Builders. Something like this:
public class MyFacade
{
private IMyDependency dep;
public MyFacade()
{
this.dep = new DefaultDependency();
}
public MyFacade WithDependency(IMyDependency dependency)
{
this.dep = dependency;
return this;
}
public Foo CreateFoo()
{
return new Foo(this.dep);
}
}
This would allow a user to create a default Foo by writing
var foo = new MyFacade().CreateFoo();
It would, however, be very discoverable that it's possible to supply a custom dependency, and you could write
var foo = new MyFacade().WithDependency(new CustomDependency()).CreateFoo();
If you imagine that the MyFacade class encapsulates a lot of different dependencies, I hope it's clear how it would provide proper defaults while still making extensibility discoverable.
FWIW, long after writing this answer, I expanded upon the concepts herein and wrote a longer blog post about DI-Friendly Libraries, and a companion post about DI-Friendly Frameworks.
The term "dependency injection" doesn't specifically have anything to do with an IoC container at all, even though you tend to see them mentioned together. It simply means that instead of writing your code like this:
public class Service
{
public Service()
{
}
public void DoSomething()
{
SqlConnection connection = new SqlConnection("some connection string");
WindowsIdentity identity = WindowsIdentity.GetCurrent();
// Do something with connection and identity variables
}
}
You write it like this:
public class Service
{
public Service(IDbConnection connection, IIdentity identity)
{
this.Connection = connection;
this.Identity = identity;
}
public void DoSomething()
{
// Do something with Connection and Identity properties
}
protected IDbConnection Connection { get; private set; }
protected IIdentity Identity { get; private set; }
}
That is, you do two things when you write your code:
Rely on interfaces instead of classes whenever you think that the implementation might need to be changed;
Instead of creating instances of these interfaces inside a class, pass them as constructor arguments (alternatively, they could be assigned to public properties; the former is constructor injection, the latter is property injection).
None of this presupposes the existence of any DI library, and it doesn't really make the code any more difficult to write without one.
If you're looking for an example of this, look no further than the .NET Framework itself:
List<T> implements IList<T>. If you design your class to use IList<T> (or IEnumerable<T>), you can take advantage of concepts like lazy-loading, as Linq to SQL, Linq to Entities, and NHibernate all do behind the scenes, usually through property injection. Some framework classes actually accept an IList<T> as a constructor argument, such as BindingList<T>, which is used for several data binding features.
Linq to SQL and EF are built entirely around the IDbConnection and related interfaces, which can be passed in via the public constructors. You don't need to use them, though; the default constructors work just fine with a connection string sitting in a configuration file somewhere.
If you ever work on WinForms components you deal with "services", like INameCreationService or IExtenderProviderService. You don't even really know what what the concrete classes are. .NET actually has its own IoC container, IContainer, which gets used for this, and the Component class has a GetService method which is the actual service locator. Of course, nothing prevents you from using any or all of these interfaces without the IContainer or that particular locator. The services themselves are only loosely-coupled with the container.
Contracts in WCF are built entirely around interfaces. The actual concrete service class is usually referenced by name in a configuration file, which is essentially DI. Many people don't realize this but it is entirely possible to swap out this configuration system with another IoC container. Perhaps more interestingly, the service behaviors are all instances of IServiceBehavior which can be added later. Again, you could easily wire this into an IoC container and have it pick the relevant behaviors, but the feature is completely usable without one.
And so on and so forth. You'll find DI all over the place in .NET, it's just that normally it's done so seamlessly that you don't even think of it as DI.
If you want to design your DI-enabled library for maximum usability then the best suggestion is probably to supply your own default IoC implementation using a lightweight container. IContainer is a great choice for this because it's a part of the .NET Framework itself.
EDIT 2015: time has passed, I realize now that this whole thing was a huge mistake. IoC containers are terrible and DI is a very poor way to deal with side effects. Effectively, all of the answers here (and the question itself) are to be avoided. Simply be aware of side effects, separate them from pure code, and everything else either falls into place or is irrelevant and unnecessary complexity.
Original answer follows:
I had to face this same decision while developing SolrNet. I started with the goal of being DI-friendly and container-agnostic, but as I added more and more internal components, the internal factories quickly became unmanageable and the resulting library was inflexible.
I ended up writing my own very simple embedded IoC container while also providing a Windsor facility and a Ninject module. Integrating the library with other containers is just a matter of properly wiring the components, so I could easily integrate it with Autofac, Unity, StructureMap, whatever.
The downside of this is that I lost the ability to just new up the service. I also took a dependency on CommonServiceLocator which I could have avoided (I might refactor it out in the future) to make the embedded container easier to implement.
More details in this blog post.
MassTransit seems to rely on something similar. It has an IObjectBuilder interface which is really CommonServiceLocator's IServiceLocator with a couple more methods, then it implements this for each container, i.e. NinjectObjectBuilder and a regular module/facility, i.e. MassTransitModule. Then it relies on IObjectBuilder to instantiate what it needs. This is a valid approach of course, but personally I don't like it very much since it's actually passing around the container too much, using it as a service locator.
MonoRail implements its own container as well, which implements good old IServiceProvider. This container is used throughout this framework through an interface that exposes well-known services. To get the concrete container, it has a built-in service provider locator. The Windsor facility points this service provider locator to Windsor, making it the selected service provider.
Bottom line: there is no perfect solution. As with any design decision, this issue demands a balance between flexibility, maintainability and convenience.
What I would do is design my library in a DI container agnostic way to limit the dependency on the container as much as possible. This allows to swap out on DI container for another if need be.
Then expose the layer above the DI logic to the users of the library so that they can use whatever framework you chose through your interface. This way they can still use DI functionality that you exposed and they are free to use any other framework for their own purposes.
Allowing the users of the library to plug their own DI framework seems a bit wrong to me as it dramatically increases amount of maintenance. This also then becomes more of a plugin environment than straight DI.

Categories