I have been looking at various dependency injection frameworks for .NET as I feel the project I am working on would greatly benefit from it. While I think I have a good grasp of
I have a similar case related to the "expensive to create and might be used", where in my own IoC implementation, I'm adding automagic support for factory services.
Basically, instead of this:
public SomeService(ICDBurner burner)
{
}
you would do this:
public SomeService(IServiceFactory burnerFactory)
{
}
ICDBurner burner = burnerFactory.Create();
This has two advantages:
The factory object is rather easy to make, and solves a lot of problems.
Here's my factory class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LVK.IoC.Interfaces;
using System.Diagnostics;
namespace LVK.IoC
{
///
/// This class is used to implement for all
/// services automatically.
///
[DebuggerDisplay("AutoServiceFactory (Type={typeof(T)}, Policy={Policy})")]
internal class AutoServiceFactory : ServiceBase, IServiceFactory
{
#region Private Fields
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly String _Policy;
#endregion
#region Construction & Destruction
///
/// Initializes a new instance of the class.
///
/// The service container involved.
/// The policy to use when resolving the service.
/// is null .
public AutoServiceFactory(IServiceContainer serviceContainer, String policy)
: base(serviceContainer)
{
_Policy = policy;
}
///
/// Initializes a new instance of the class.
///
/// The service container involved.
/// is null .
public AutoServiceFactory(IServiceContainer serviceContainer)
: this(serviceContainer, null)
{
// Do nothing here
}
#endregion
#region Public Properties
///
/// Gets the policy that will be used when the service is resolved.
///
public String Policy
{
get
{
return _Policy;
}
}
#endregion
#region IServiceFactory Members
///
/// Constructs a new service of the correct type and returns it.
///
/// The created service.
public IService Create()
{
return MyServiceContainer.Resolve(_Policy);
}
#endregion
}
}
Basically, when I build the service container from my service container builder class, all service registrations are automatically given another co-service, implementing IServiceFactory for that service, unless the programmer has explicitly registered on him/her-self for that service. The above service is then used, with one parameter specifying the policy (which can be null if policies aren't used).
This allows me to do this:
var builder = new ServiceContainerBuilder();
builder.Register()
.From.ConcreteType();
using (var container = builder.Build())
{
using (var factory = container.Resolve>())
{
using (var service = factory.Instance.Create())
{
service.Instance.DoSomethingAwesomeHere();
}
}
}
Of course, a more typical use would be with your CD Burner object. In the above code I would resolve the service instead of course, but it's an illustration of what happens.
So with your cd burner service instead:
var builder = new ServiceContainerBuilder();
builder.Register()
.From.ConcreteType();
builder.Register()
.From.ConcreteType(); // constructor used in the top of answer
using (var container = builder.Build())
{
using (var service = container.Resolve())
{
service.Instance.DoSomethingHere();
}
}
inside the service, you could now have a service, a factory service, which knows how to resolve your cd burner service upon request. This is useful for the following reasons:
Here's two at the same time:
using (var service1 = container.Resolve())
using (var service2 = container.Resolve())
{
service1.Instance.DoSomethingHere();
service2.Instance.DoSomethingHere();
}
Here's two after each other, not reusing the same service:
using (var service = container.Resolve())
{
service.Instance.DoSomethingHere();
}
using (var service = container.Resolve())
{
service.Instance.DoSomethingElseHere();
}