Autofac入门示例–下 - 计算器

上篇已经简单的演示了一个使用Autofac实现的备忘录模型,这次我们来演示一下官方的范例计算器Calculator。该示例使用了多个项目更清晰的体现了IoC的本领。

原文的地址:http://www.java2s.com/Open-Source/CSharp/Inversion-of-Control-Dependency-Injection/Autofac/Calculator/CatalogCalculator.htm(英文)

源程序下载:https://files.cnblogs.com/xupng/Calculator.rar

先看一下整体的截图:
image

依旧延续上篇的介绍风格,进行一个整体的介绍,该范例实现了一个简单的计算器功能,定义了一套计算接口,各种操作(+-*/等等)都在另外一个项目中实现,当需要增加或修改一种计算方式时只需要在实现的工程中进行增减或是增加其它的工程,而无须修改主程序,主程使用Autofac进行依赖注入,使用了配置文件注册各种操作的实现。

Calculator.Api工程中定义了接口,所有的操作都实现这该工程的接口。

namespace Calculator.Api
{
    public interface INotifier
    {
        void Notify(string message);
    }
    public interface IOperation
    {
        string Operator { get; }
        double Apply(double lhs, double rhs);
    }
}

Calculator.Operations工程中定义了加法和除法的实现,除法中定义了保留几位小数和当被0除时抛出一个提示。

namespace Calculator.Operations
{
    public class Add : IOperation
    {
        public string Operator
        {
            get { return "+"; }
        }

        public double Apply(double lhs, double rhs)
        {
            return lhs + rhs;
        }
    }

    public class Divide : IOperation
    {
        INotifier _notifier;
        int _places;

        public Divide(INotifier notifier, int places)
        {
            if (notifier == null)
                throw new ArgumentNullException("notifier");
            _notifier = notifier;
            _places = places;
        }

        public string Operator
        {
            get { return "/"; }
        }

        public double Apply(double lhs, double rhs)
        {
            if (rhs == 0.0)
            {
                _notifier.Notify("初除数不能为0。");
                return double.NaN;
            }

            return Math.Round(lhs / rhs, _places);
        }
    }

}
程序的骨架搭建完成后现在开始介绍客户代码的工程Calculator,该工程中的三个注意点:
  • App.config中autofac配置节,是如何使用配置文件实现组件和服务的注册的。
  • Programe.cs中的Main入口,在程序入口时用Autofac进行注册程序中所使用的组件和服务,类和接口,并调用RegisterModule(new ConfigurationSettingReader(“autofac”))方法注册配置文件中的组件服务。
  • 为CalculatorForm增加构造方法,构造时传入业务逻辑处理类Calculator,并在Main入口入启动窗体时Resolve出该窗体,Autofac会自动为我们装配好我们所需要的一切。
好了,带着三个注意点我们来看一下App.config
<configuration>
  <configSections>
    <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
  </configSections>
  <autofac defaultAssembly="Calculator.Api">
    <components>
      <component type="Calculator.Operations.Add,Calculator.Operations" service="Calculator.Api.IOperation" />
      <component type="Calculator.Operations.Divide,Calculator.Operations" service="Calculator.Api.IOperation" >
        <parameters>
          <parameter name="places" value="4" />
        </parameters>
      </component>
    </components>
  </autofac>
</configuration>

我们看到Divide配置节里不家一个parameter的配置节,名字是places,该配置节就是告诉Autofac在Divide中的places属性为4,就是保留4位小数。这样有一天我们需要修改为保留2位小数的话,只需要修改配置文件即可。

Calculator是一个业务逻辑类,为了便于测试和职责单一原则,于是将其与CalculatorForm进行了分离,我们可以对该业务逻辑和Form分别进行单独的单元测试,至于如何单元测试已经超出了本文的介绍,我会在以后的文章里专门的介绍单元测试的内容。

    public class Calculator
    {
        IDictionary<string, IOperation> _operations = new Dictionary<string, IOperation>();

        public Calculator(IEnumerable<IOperation> operations)
        {
            if (operations == null)
                throw new Exception("没有可用的操作");

            foreach (IOperation op in operations)
                _operations.Add(op.Operator, op);
        }

        public IEnumerable<string> AvailableOperators
        {
            get { return _operations.Keys; }
        }

        public double ApplyOperation(string operation, double rhs, double lhs)
        {
            IOperation op;
            if (!_operations.TryGetValue(operation, out op))
                throw new Exception("无效的操作符");
            return op.Apply(lhs, rhs);
        }
    }

计算器的功能就介绍范例就介绍到这里,如果有什么疑问可以给我留言,还是象以前一样,建议同志们把代码自己敲一遍加深理解,而不要看看了之。

下一篇我们将详细讲解它常用的方法和一些使用技巧

posted @ 2011-07-13 23:51  碧玉软件  阅读(445)  评论(0编辑  收藏  举报