Many open source projects use a Configuration class and lambda’s to clarify configuring a complex object. Take Mass Transit for example. A simple configuration would be like so.
Bus.Initialize(sbc =>
{
sbc.UseMsmq();
sbc.VerifyMsmqConfiguration();
sbc.VerifyMsDtcConfiguration();
sbc.UseMulticastSubscriptionClient();
sbc.ReceiveFrom("msmq://localhost/test");
});
When you hover over Initialize in Visual Studio it says the parameter for the method call is Action<ServiceBusConfigurator>. I was wondering if anyone could show a simple example of how to use this pattern on a class. I don’t even know what to call this type of pattern and my “GoogleFu” is not working as of yet. In this particular case I realize the method is operating on a singleton pattern. But I am ok with it being an instance method on a class.
An
Action<ServiceBusConfigurator>is a method which accepts a single parameter of typeServiceBusConfigurator, does an “action” operating on that instance, and returns nothing (void)..NET BCL (starting from 3.5) comes with predefined generic delegate signatures:
Action<T>,Action<T1, T2>(etc.) for methods which don’t return a value, andFunc<Tresult>,Func<T, Tresult>(etc.) for methods accepting zero of more parameters and returning a single result instance of typeTresult.When you create a method which accepts a delegate, you allow callers of your method to pass more than just data parameters – your method actually delegates a part of responsibility to external code. In your case,
Bus.Initializecreates an instance ofServiceBusConfigurator(sbc), and then calls the specified action with thesbcinstance as the parameter.This basically lets your method control the lifetime of the configuration class instance. It is up to the caller to fill in the details, but actual instance is provided by your class:
The benefit is that your built instance (the imaginary
IBusin this case) cannot be modified further. Configuration instance is only created shortly, passed to an external method, and then used to create an immutable final object:Two things to note in the line above:
The code inside the anonymous method is wrapped inside a delegate passed to the method. It is not executed until the
Configuremethod actually calls it.The
cfgparameter is created by theConfiguremethod and passed to the lambda. After the method returns, this object doesn’t exist anymore (or is wrapped inside the resulting object).