65.9K
CodeProject 正在变化。 阅读更多。
Home

Unity应用程序块入门

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.95/5 (20投票s)

2009年9月21日

CPOL

2分钟阅读

viewsIcon

100218

Unity 应用块、控制反转和依赖注入。

引言

随着最新版本的发布,微软的 Enterprise Library 引入了一个名为 Unity 的新组件。这个应用块提供了一种简单的方法来实现 IoC 模式,从而实现依赖注入模式。

关于 Enterprise Library 文档的所有参考资料都可以在文章末尾找到。

背景

理解 Unity 的工作原理及其在项目中带来的好处的关键在于控制反转和依赖注入。 如果您想深入了解这些模式:https://martinfowler.com.cn/articles/injection.html

本文的范围是编写松散耦合的代码。 让我们检查以下 DummyLogger

public class DummyLogger
{
    private IWriter _selectedWriter;

    public DummyLogger()
    {
        //The container class is in charge for the initialization of the interface. 
        //the result is a strong dependency between the two objects
        _selectedWriter = new ConsoleWriter();
    }

    public void WriteOutput(string msg)
    {
        _selectedWriter.Write(msg);
    }
}

打破两个对象之间关系的第一件事是将类成员的创建委托给其他人

public class DummyLogger
{
    private IWriter _selectedWriter;

    public void SetWriter(IWriter writer)
    {
        _selectedWriter = writer;
    }

    public void WriteOutput(string msg)
    {
        _selectedWriter.Write(msg);
    }
}

到目前为止,没什么新鲜的。 这可以解释为 IoC 模式的一个简单的实现。 包含的对象不再由其容器类控制。

但是,如果我们不关心 IWriter 接口的实际实现呢? 这就是 Unity 和依赖注入发挥作用的地方。 类成员的具体实现将由 Unity 根据其配置“注入”。 我们首先需要使用其 get/set 方法公开类/接口,并使用 [Dependency] 属性对其进行标记,以便使其对应用块可见。

public class DummyLogger
{

    private IWriter _selectedWriter;

    public void SetWriter(IWriter writer)
    {
        _selectedWriter = writer;
    }

    public void WriteOutput(string msg)
    {
        _selectedWriter.Write(msg);
    }
}

在幕后,用 [Dependency] 属性装饰的每个类/接口都将根据 Unity 容器的配置进行创建。 这可以通过编程方式或通过 .config 文件来完成。

<type type="George2giga.TestUnity.Library.IWriter,George2giga.TestUnity.Library" 
   mapTo="George2giga.TestUnity.Library.ConsoleWriter,George2giga.TestUnity.Library" />

使用代码

下面是一个 Unity 的基本实现。 这是我们示例应用程序的类图

IWriter 接口在日志提供程序之间共享

public interface IWriter
{
    void Write(string msg);
}

在三个日志提供程序中,根据配置,其中一个将被“注入”以创建 IWriter 实例

public class ConsoleWriter : IWriter
{
    #region IWriter Members

    public void Write(string msg)
    {
        Console.WriteLine(msg);
        Console.ReadLine();
    }

    #endregion
}

public class FileWriter : IWriter
{
    #region IWriter Members

    public void Write(string msg)
    {
        using (StreamWriter streamWriter = 
               new StreamWriter("c:\\TestUnity.txt",true))
        {
            streamWriter.WriteLine(msg);
        }
    }
    #endregion
}

public class EventViewerWriter : IWriter
{
    #region IWriter Members

    public void Write(string msg)
    {
        EventLog.WriteEntry("TestUnity", msg, 
                            EventLogEntryType.Information);
    }

    #endregion
}

日志类包含依赖属性

public class DummyLogger
{
    private IWriter selectedWriter;

    [Dependency]
    public IWriter SelectedWriter
    {
        get { return selectedWriter; }
        set { selectedWriter = value; }
    }

    public void WriteOutput(string msg)
    {
        selectedWriter.Write(msg);
    }
}

应用程序的入口点负责初始化 Unity 容器

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer();
        UnityConfigurationSection section = 
          (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
        section.Containers.Default.Configure(container);
        DummyLogger dummyLogger = container.Resolve<DummyLogger>();
        dummyLogger.SelectedWriter.Write("Hello");}
}

以下是 App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
      <section name="unity" 
         type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, 
               Microsoft.Practices.Unity.Configuration" />
    </configSections>
    <unity>
      <containers>
        <container>
          <types>
            <type 
               type="George2giga.TestUnity.Library.IWriter,George2giga.TestUnity.Library" 
               mapTo="George2giga.TestUnity.Library.ConsoleWriter,
                      George2giga.TestUnity.Library" />
          </types>
        </container>
      </containers>
    </unity>
</configuration>

关注点

设计模式无疑是一个非常有趣的论点。 使用 Unity,我们可以以非常简单的方式实现其中两种模式。 依赖注入允许我们创建解耦的代码,我们可以在不进行任何硬编码的情况下创建依赖项。

参考文献

© . All rights reserved.