使用依赖注入的.NET Framework对象?

时间:2010-10-04 13:18:04

标签: .net dependency-injection

我试图在.NET中找到一个使用Dependancy Injection的类的示例(例如,使用 Builder Factory <的类/ strong>为了创建完整的对象 - 像它一样注入依赖项

浏览Reflector,我原本以为一些更复杂的ado.netWebRequest对象会使用依赖注入 - 但不是。

任何人都可以指向一个使用依赖注入来完成其工作的对象的.NET框架内的示例吗?

4 个答案:

答案 0 :(得分:3)

以下是框架中依赖注入的几个示例:

WCF的ChannelDispatcher具有IChannelListener的构造函数注入(强制依赖)。通常,WCF relies on configuration可以对用户级别的可选依赖项进行注入。

System.Xml可以在很多地方进行穷人的依赖注入。例如,XmlDocument在XmlImplementation上有一个构造函数注入(内部)。默认构造函数只是实例化所需的XmlImplementation。 XmlImplementation本身依赖于XmlNameTable。 XmlResolvers是另一个注入的例子。

MEF的CompositionContainer可选择依赖于ComposablePartCatalog和ExportProviders。 ImportEngine具有ExportProvider的构造函数注入

ASP.NET MVC的Controller在IActionInvoker和ITempDataProvider上有setter注入(它们有默认实现) 模型粘合剂也是可注射的。

如果您刚开始使用依赖注入,恕我直言,.NET框架是您可以学习的最糟糕的地方:大多数时候您将没有源代码,它是框架级别(不是应用程序级别) )具有特殊要求的代码。特别是微软非常小心公开(默认是内部的),而不是大多数开源项目,以便更好地管理他们的重大变化。

答案 1 :(得分:2)

.NET Framework中有很多地方使用依赖注入。首先,.NET Framework使用了大量的GoF模式,其中一些模式很大程度上依赖于依赖注入。例如,Decorator Design Pattern始终使用构造函数注入,Strategy Design Pattern使用构造函数注入或方法注入:

// Decorator on Streams (uses Constructor Injection)
var ms = new MemoryStream();
var bs = new BufferedStream(ms);

// Strategy of sorting (uses Method Injection)
var list = new List<int>();
list.Sort(new CustomComparer());

// Strategy of sorting (Constructor Injection)
var sortedArray = new SortedList<int, string>(
                        new CustomComparer());

// Strategy of starting new task using TaskScheduler
// (Method Injection)
var task = Task.Factory.StartNew(
    () => { }, 
    CancellationToken.None, 
    TaskCreationOptions.None, 
    TaskScheduler.Default);

    // All method that takes IFormatProvider and
    // similar strategies is an example of the Method Injection
    IFormatProvider provider = null;
    42.ToString(provider);

Abstract Factory Design Pattern的任何使用意味着您将使用构造函数注入或方法注入“注入”工厂对象,并且此类模式的.NET Framework中有大量示例,如DbProviderFactory

为了获得更多示例,将显示哪些BCL类型使用构造函数注入,我编写了一个简单的LINQ查询(我将在稍后展示)枚举所有可访问类型以查找具有接受接口的公共构造函数的类型或抽象类型作为参数。此查询显示了.NET Framework中的构造函数注入的许多其他用法(此处为一些示例):

// ResourceReader takes a Stream
Stream ms = new MemoryStream();
var resourceReader = new ResourceReader(ms);

// BinaryReader/BinaryWriter, StreamReader/StreamWriter
// takes a Stream as well
var textReader = new StreamReader(ms);

// MethodCall takes a IMessage
IMessage message = new System.Runtime.Remoting.Messaging.MethodResponse(null, null);
var methodCall = new System.Runtime.Remoting.Messaging.MethodCall(message);

// Icon takes a Stream
var icon = new System.Drawing.Icon(ms);

// DbEnumerator takes a IDataReader
IDataReader dataReader = new DataTableReader(new DataTable());
var dbEnumerator = new System.Data.Common.DbEnumerator(dataReader);

这只是有限的类型列表,.NET Framework包含许多依赖于此技术的类型。构造函数注入是在这个术语出现之前很久就被广泛使用的技术,所以我对它的使用如此广泛并不感到惊讶。您可以使用以下LINQ查询来获取更多其他构造函数注入示例(稍作修改,您可以编写一个查找方法注入模式的查询):

var types =
    AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(a => a.GetTypes())
        .SelectMany(t => t.GetConstructors()
                                .Where(c => c.GetParameters()
                                                .Any(cp =>
                                                    (cp.ParameterType.IsAbstract ||
                                                    cp.ParameterType.IsInterface))))

        .Select(ci => new {Type = ci.DeclaringType, Constructor = ci.GetConstructorInfo()})
        .Where(t => !t.Type.Namespace.Contains("Internal"));

答案 2 :(得分:1)

我认为整个.NET框架中都存在DI,但它是DI的一种特殊形式,称为“Property Injection” - 在Java世界中,它经常被称为“Setter Injection”。

答案 3 :(得分:0)

这是一个真正简单(愚蠢)的通过工厂进行依赖注入的例子:

public class MyService1Factory {
    public IMyService1 Create() {
        MyService2 service = new MyService2();
        // provides dependent IMyService2 for MyService
        return new MyService(service);
    }
}

public class MyService : IMyService1 {
    private IMyService2 service;

    // MyService depends upon IMyService2, an instance of this "dependency" is 
    // passed in (or "injected") via a simple constructor param
    public MyService(IMyService2 myService2) {
        service = myService2;
    }
}