C#中使用lambda的流畅接口配置

Mat*_*ips 8 c# configuration lambda design-patterns

许多开源项目使用Configuration类和lambda来阐明配置复杂对象.以Mass Transit为例.一个简单的配置就是这样.

Bus.Initialize(sbc =>
        {
            sbc.UseMsmq();
            sbc.VerifyMsmqConfiguration();
            sbc.VerifyMsDtcConfiguration();
            sbc.UseMulticastSubscriptionClient();
            sbc.ReceiveFrom("msmq://localhost/test");
        });
Run Code Online (Sandbox Code Playgroud)

当您将鼠标悬停Initialize在Visual Studio中时,它表示方法调用的参数是Action<ServiceBusConfigurator>.我想知道是否有人能够展示如何在课堂上使用这种模式的简单例子.我甚至不知道该怎么称呼这种模式,而我的"GoogleFu"尚未发挥作用.在这种特殊情况下,我意识到该方法是在单例模式下运行的.但我很好,它是一个类的实例方法.

Gro*_*roo 7

An Action<ServiceBusConfigurator>是一种接受单个类型参数的方法,ServiceBusConfigurator对该实例执行"操作"操作,并返回nothing(void).

.NET BCL(从3.5开始)带有预定义的通用代表签名:Action<T>,Action<T1, T2>(等)不返回一个值,和方法Func<Tresult>,Func<T, Tresult>对于方法接受更多的参数的零和返回的单个结果实例(等)类型Tresult.

当您创建一个接受委托的方法时,您允许方法的调用者传递的不仅仅是数据参数 - 您的方法实际上将一部分责任委托给外部代码.在您的情况下,Bus.Initialize创建ServiceBusConfigurator(sbc)的实例,然后使用sbc实例作为参数调用指定的操作.

这基本上允许您的方法控制配置类实例的生命周期.由调用者填写详细信息,但实际的实例由您的类提供:

 // this is not actual mass transit source code
 public class BusCreator
 {
     public static IBus Initialize(Action<IConfiguration> action)
     {
         // create the config instance here
         IConfiguration config = CreateDefaultConfig();

         // let callers modify it
         action(config);

         // use the final version to build the result
         return config.Build()
     }
 }
Run Code Online (Sandbox Code Playgroud)

好处是您的构建实例(IBus在这种情况下是虚构的)无法进一步修改.配置实例仅在短时间内创建,传递给外部方法,然后用于创建不可变的最终对象:

 IBus result = BusCreator.Configure(cfg => cfg.BusType = BusType.MSMQ);
Run Code Online (Sandbox Code Playgroud)

上面两行要注意的事项:

  1. 匿名方法中的代码包含在传递给方法的委托中.直到Configure方法实际调用它才会执行.

  2. cfg参数由Configure方法创建并传递给lambda.方法返回后,此对象不再存在(或包含在生成的对象中).