Siempre escribo un contenedor de Adaptador para cualquier Contenedor IoC, que se ve así:
public static class Ioc
{
public static IIocContainer Container { get; set; }
}
public interface IIocContainer
{
object Get(Type type);
T Get<T>();
T Get<T>(string name, string value);
void Inject(object item);
T TryGet<T>();
}
Para Ninject, específicamente, la clase de adaptador concreta se ve así:
public class NinjectIocContainer : IIocContainer
{
public readonly IKernel Kernel;
public NinjectIocContainer(params INinjectModule[] modules)
{
Kernel = new StandardKernel(modules);
new AutoWirePropertyHeuristic(Kernel);
}
private NinjectIocContainer()
{
Kernel = new StandardKernel();
Kernel.Load(AppDomain.CurrentDomain.GetAssemblies());
new AutoWirePropertyHeuristic(Kernel);
}
public object Get(Type type)
{
try
{
return Kernel.Get(type);
}
catch (ActivationException exception)
{
throw new TypeNotResolvedException(exception);
}
}
public T TryGet<T>()
{
return Kernel.TryGet<T>();
}
public T Get<T>()
{
try
{
return Kernel.Get<T>();
}
catch (ActivationException exception)
{
throw new TypeNotResolvedException(exception);
}
}
public T Get<T>(string name, string value)
{
var result = Kernel.TryGet<T>(metadata => metadata.Has(name) &&
(string.Equals(metadata.Get<string>(name), value,
StringComparison.InvariantCultureIgnoreCase)));
if (Equals(result, default(T))) throw new TypeNotResolvedException(null);
return result;
}
public void Inject(object item)
{
Kernel.Inject(item);
}
}
La razón principal para hacer esto es abstraer el marco de IoC, de modo que pueda reemplazarlo en cualquier momento, dado que la diferencia entre los marcos generalmente está en la configuración y no en el uso.
Pero, como beneficio adicional, las cosas también se vuelven mucho más fáciles para usar el marco de IoC dentro de otros marcos que no lo admiten de manera inadvertida. Para WinForms, por ejemplo, son dos pasos:
En su método Main, simplemente cree una instancia de un contenedor antes de hacer cualquier otra cosa.
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
try
{
Ioc.Container = new NinjectIocContainer( /* include modules here */ );
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyStartupForm());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
Y luego tenga una Forma base, de la cual derivan otras formas, que llama Inyectar sobre sí misma.
public IocForm : Form
{
public IocForm() : base()
{
Ioc.Container.Inject(this);
}
}
Esto le dice a la heurística de cableado automático que intente inyectar recursivamente todas las propiedades en la forma que se ajuste a las reglas establecidas en sus módulos.