术语“依赖注入”与IoC容器没有任何特别的关系,尽管您经常看到它们一起被提到。它只是意味着不要像这样写代码:
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
}
}
你可以这样写:
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; }
}
也就是说,当你编写代码时,你要做两件事:
当您认为实现可能需要更改时,依赖接口而不是类;
与其在类中创建这些接口的实例,不如将它们作为构造函数参数传递(或者,它们可以被分配给公共属性;前者是构造函数注入,后者是属性注入)。
这些都不以DI库的存在为前提,没有DI库也不会使代码更难编写。
如果你正在寻找这样的例子,只需看看.NET框架本身:
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.
诸如此类。你会发现。net中到处都是DI,只是通常情况下,它是如此无缝地完成,以至于你甚至不认为它是DI。
如果您希望设计支持di的库以获得最大的可用性,那么最好的建议可能是使用轻量级容器提供您自己的默认IoC实现。IContainer是一个很好的选择,因为它是. net框架本身的一部分。