Tôi luôn viết một trình bao bọc Bộ điều hợp cho bất kỳ Container IoC nào, trông giống như sau:
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>();
}
Đối với Ninject, cụ thể, lớp Adaptor cụ thể trông như thế này:
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);
}
}
Lý do chính để thực hiện điều này là để trừu tượng hóa khung IoC, vì vậy tôi có thể thay thế nó bất cứ lúc nào - với điều kiện là sự khác biệt giữa các khung nói chung là về cấu hình thay vì sử dụng.
Nhưng, như một phần thưởng, mọi thứ cũng trở nên dễ dàng hơn rất nhiều khi sử dụng khung IoC bên trong các khung công tác khác vốn không hỗ trợ nó. Ví dụ, đối với WinForms, có hai bước:
Trong phương thức chính của bạn, chỉ cần khởi tạo một container trước khi làm bất cứ điều gì khác.
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());
}
}
}
Và sau đó có một Biểu mẫu cơ sở, từ đó các hình thức khác xuất phát, gọi chính là Tiêm.
public IocForm : Form
{
public IocForm() : base()
{
Ioc.Container.Inject(this);
}
}
Điều này cho biết heuristic tự động nối dây để cố gắng đệ quy tất cả các thuộc tính ở dạng phù hợp với các quy tắc được thiết lập trong các mô-đun của bạn.