Я всегда пишу оболочку адаптера для любого контейнера IoC, которая выглядит следующим образом:
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>();
}
В частности, для Ninject конкретный класс Adapter выглядит следующим образом:
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);
}
}
Основная причина для этого состоит в том, чтобы абстрагировать платформу IoC, чтобы я мог заменить ее в любое время, учитывая, что разница между платформами обычно заключается в конфигурации, а не в использовании.
Но, в качестве бонуса, также становится намного проще использовать IoC-фреймворк внутри других фреймворков, которые не поддерживают его. Для WinForms, например, это два шага:
В вашем методе Main просто создайте экземпляр контейнера, прежде чем делать что-либо еще.
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());
}
}
}
И тогда есть базовая форма, из которой происходят другие формы, которая вызывает Inject для себя.
public IocForm : Form
{
public IocForm() : base()
{
Ioc.Container.Inject(this);
}
}
Это говорит эвристике автоматического подключения пытаться рекурсивно внедрить все свойства в форме, которые соответствуют правилам, установленным в ваших модулях.