How to: inject StateValue<T> objects using constructor injection
January 12th, 2007
The Composite Web Application Block included in the Web Client Software Factory has a very useful class named StateValue that allows you to use the ASP.NET Session and still keep you classes testable. To use it, you just have to declare a public field in your class as shown in the following code:
public StateValue<Customer> _currentCustomer;
By doing this, ObjectBuilder knows that it has to inject an instance of the StateValue class for you, so you can use it by accessing the Value property:
// Set the value _currentCustomer.Value = new Customer(); // Get the value Customer customer = _currentCustomer.Value;
Note that the StateValue field has to be public because ObjectBuilder only reflects over public members. For more information regarding the StateValue class and how this class helps you unit test your classes, see How to: Use Session State with Unit Testing in the WC-SF documentation.
Since ObjectBuilder is a very flexible framework, you can create a special attribute (let’s call it “SessionDependency”) to indicate to ObjectBuilder that it has to inject a StateValue object during the creation of your class. This would make your code look like this:
private StateValue<Customer> _currentCustomer; public CustomersController ( // Indicate to ObjectBuilder that we need // a StateValue object // “CurrentCustomer” is the Session key name [SessionDependency("CurrentCustomer")] StateValue<Customer> currentCustomer ) { _currentCustomer = currentCustomer; }
How is this achieved?
ObjectBuilder contains a base class named ParameterAttribute you can derive from to create attributes that can be applied to parameters in methods. This class is very simple:
public abstract class ParameterAttribute : Attribute { protected ParameterAttribute(); public abstract IParameter CreateParameter(Type memberType); }
The CreateParameter method must return an instance that implements the IParameter interface. This interface represents a parameter in a method, and contains the following members:
public interface IParameter { Type GetParameterType(IBuilderContext context); object GetValue(IBuilderContext context); }
The GetValue method returns the value for the parameter. The value is used by ObjectBuilder to call an injection method (a method, or a constructor) and pass the value to it.
Well, now that you are more familiar with the ParameterAttribute class and the IParameter interface, let’s see the implementation of the SessionDependency attribute:
[AttributeUsage(AttributeTargets.Parameter)] public class SessionDependencyAttribute : ParameterAttribute { private string _keyName; public SessionDependencyAttribute(string keyName) { _keyName = keyName; } public override IParameter CreateParameter(Type memberType) { return new SessionDependencyParameter(memberType, _keyName); } }
As you can see, the implementation it’s pretty simple:
- It contains a constructor that recieves a Session key name as a parameter.
- The CreateParameter method returns an instance of the SessionDependencyParameter class.
This is the code for the SessionDependencyParameter class:
class SessionDependencyParameter : IParameter { private Type _memberType; private string _keyName; public SessionDependencyParameter(Type memberType, string keyName) { _memberType = memberType; _keyName = keyName; } #region IParameter Members public Type GetParameterType(IBuilderContext context) { return _memberType; } public object GetValue(IBuilderContext context) { ISessionStateLocatorService sessionLocator = context.Locator.Get<ISessionStateLocatorService>(new DependencyResolutionLocatorKey(typeof(ISessionStateLocatorService), null)); if (sessionLocator != null) { IStateValue value = (IStateValue)Activator.CreateInstance(_memberType); value.SessionState = sessionLocator.GetSessionState(); value.KeyName = _keyName; return value; } return null; } #endregion }
The key in the code above is the implmentation of the GetValue method. What it does is very similar to what the SessionStateBindingStrategy class included in the Composite Web Application Block does:
- Gets a ISessionStateLocatorService. This service is used to get a valid System.Web.SessionState.IHttpSessionState object. By using this service, we avoid having a direct reference to the Session bag of the current ASP.NET request context, thus making the class more testable.
- Creates an instance of the StateValue class.
- Sets the SessionState property to the Session bag returned by the ISessionStateLocatorService.
- Sets the KeyName property with the key name specified in the parameter of the SessionDependency attribute.
- Returns the initialized StateValue instance. Note that if no ISessionStateLocatorService is found, null is returned.
Source Code
- You can get the source code of the SessionDependencyAttribute implementation by downloading the file CompositeWeb.Extensions.zip (see below).
- To use it, open the solution and build it. If you experience problems, make sure that the refences to the Composite Web Application Block and ObjectBuilder assemblies are correct. Then add a reference in your business modules to the CompositeWeb.Extensions.dll assembly.
- Important: The code is provided “as is” with no warranties of any kind.
To include this in the Web Client Development guidance package
In a future post I’ll blog about how to add this to the Web Client Development guidance package, so stay tunned

January 12th, 2007 at 8:16 pm
Nice! I like it.
January 12th, 2007 at 9:27 pm
Nice! I wish we would have given the ISessionLocatorService a better name - like IStateLocatorService.
What would happen if you someone took a simliar approach that took the ’state name’ to be the name of a query and get parameters to somehow run it against the DB? Would it be possible to make a simple system that by injection allowed you to get the database data you need as well? Interesting pattern to explore, and see what would happen if you need parameters etc.
January 14th, 2007 at 4:21 am
Hi Ed, that is a fantastic idea! I’m sure that something like that can be developed. For sure, an interesting area to explore.
Thanks
Mariano
January 16th, 2007 at 3:58 pm
The only change I would have done is
AttributeTargets.Parameter => AttributeTargets.Property | AttributeTargets.Parameter
January 15th, 2008 at 1:09 am
In October WCSF Automation guidance, I can not find SessionDependency but there is StateDependency attribute, which is I believe how it is called now
Can you just confirm that is correct presumption of mine?
Thanks,
Nikola