Saturday, June 4, 2011

Self constructing 'Null' objects with Unity

This post follows on from the musings on proxies and Null objects. As I opined, auto constructing implementations of the Null object pattern should be possible via a proxy approach - hence here, I show one way of doing such, using the Unity framework as a base.

The essence of the implementation is: when creating an object that needs auto construction services (that is, when a property is referenced and it is both a reference object and null - create a stand-in), wrap it in a unity interceptor, and associate with the wrapper (in my case) an 'object creation provider' object - that is responsible for providing (literally) the object creation service.

Here is the almost complete implementation, followed by an exposition on the salient points.

1:    
2:    
3:   public class AutoConstructingObjectProxy : BaseInterceptionBehavior {  
4:    
5:    private const string GetPropertyPrefix = "get_";  
6:    private static readonly Dictionary<Type, Func<object>> mHandlers =   
7:     new Dictionary<Type, Func<object>> {   
8:      { typeof(string), () => String.Empty }   
9:     };  
10:    
11:    public AutoConstructingObjectProxy(IObjectCreationProvider objectBuilder)  
12:     : base(PromiscuousPolicy) {  
13:     ObjectBuilder = objectBuilder;  
14:    }  
15:    
16:    protected override IMethodReturn ProcessInvocation(IMethodInvocation input, Func<IMethodReturn> processNext) {  
17:     IMethodReturn result = processNext();  
18:    
19:     if (result.ReturnValue == null) {  
20:      PropertyInfo info = GetProperty(input);  
21:      if (info != null) {  
22:       object constructedObject =   
23:        PrimitiveDefault(info) ??   
24:        (ConstructableProperty(info) ?   
25:         ObjectBuilder.CreateObjectFromType(info.PropertyType, true) : null);  
26:       if (constructedObject != null) {  
27:        // If, for some reason, the property is not mutable,   
28:        // then this will be an inefficient mechanism  
29:        if (info.CanWrite)  
30:         info.SetValue(input.Target, constructedObject, null);  
31:        result.ReturnValue = constructedObject;  
32:       }  
33:      }  
34:     }  
35:     return result;  
36:    }  
37:    
38:    private object PrimitiveDefault(PropertyInfo info) {  
39:     return mHandlers.ContainsKey(info.PropertyType) ? mHandlers[info.PropertyType] : null;  
40:    }  
41:    
42:    private PropertyInfo GetProperty(IMethodInvocation input) {  
43:     return !input.MethodBase.Name.StartsWith(GetPropertyPrefix) ?  
44:       null :   
45:       input.Target.GetType().GetProperty(input.MethodBase.Name.Replace(GetPropertyPrefix, String.Empty));  
46:    }  
47:    
48:    private bool ConstructableProperty(PropertyInfo info) {  
49:     return ObjectBuilder.ControlsNamespace(info.PropertyType.Namespace);  
50:    }  
51:    
52:    private IObjectCreationProvider ObjectBuilder { get; set; }  
53:    
54:   }  
55:  }  
56:    

So, of course the class declaration itself:

  • Line 5: defines the standard prefix for a property 'getter' (used in reflection later)
  • Lines 6-9: Define some handlers for objects that can't just be 'new'd' and are not constructed automagically
  • Lines 11-14: This interceptor type is constructed with an implementation of the interface IObjectCreationProvider - an object building factory if you will, that knows how to locate types to construct and then create them on demand. As part of construction, an object is passed to the base class constructor that controls how properties are to be intercepted - in this case promiscously; that is, all properties are candidates for inspection


1:    
2:    
3:   public class AutoConstructingObjectProxy : BaseInterceptionBehavior {  
4:    
5:    private const string GetPropertyPrefix = "get_";  
6:    private static readonly Dictionary<Type, Func<object>> mHandlers =   
7:     new Dictionary<Type, Func<object>> {   
8:      { typeof(string), () => String.Empty }   
9:     };  
10:    
11:    public AutoConstructingObjectProxy(IObjectCreationProvider objectBuilder)  
12:     : base(PromiscuousPolicy) {  
13:     ObjectBuilder = objectBuilder;  
14:    }  
15:       

Here's the key part.

  • Line 16: This is an override of a base class method that itself implements the Unity Invoke method (base class created by Sam Stephens, as part of our project when we refactored the previous policy injection application block implementation. And Sam, who coined the memorable phrase "social oddity" to describe my interaction with humans!) 
  • Line 17 - execute the invocation to it's result yielding conclusion
  • Line 19 - see if the return value is actually null
  • Line 20 - Call a private method that uses reflection to get a PropertyInfo object for the currently intercepted method, if one exists
  • Lines 22-25 - Declare and construct an object. If the 'standard' handlers don't provide a value (use of the coalescing operator of c#), see if the property info has a return type  such that the object creation provider can theoretically construct the object. If it can, ask the provider to create an object, and (using the true parameter) request that the returned object is itself wrapped in an auto constructing object proxy. This is obviously most important - if we auto construct a stand-in object, we need that object to also auto construct parts of itself that might be null.
  • Lines 26-30 - so, if we have an object reference now, and the property itself is writeable, insert this object into the current object (the target of the interception). Also, and again important, set the return value of the invocation to the object we constructed. There is a performance implication if the property that was located is not writeable - we'll keep creating objects every time such a property is referenced.

     
16:    protected override IMethodReturn ProcessInvocation(IMethodInvocation input, Func<IMethodReturn> processNext) {  
17:     IMethodReturn result = processNext();  
18:    
19:     if (result.ReturnValue == null) {  
20:      PropertyInfo info = GetProperty(input);  
21:      if (info != null) {  
22:       object constructedObject =   
23:        PrimitiveDefault(info) ??   
24:        (ConstructableProperty(info) ?   
25:         ObjectBuilder.CreateObjectFromType(info.PropertyType, true) : null);  
26:       if (constructedObject != null) {  
27:        // If, for some reason, the property is not mutable,   
28:        // then this will be an inefficient mechanism  
29:        if (info.CanWrite)  
30:         info.SetValue(input.Target, constructedObject, null);  
31:        result.ReturnValue = constructedObject;  
32:       }  
33:      }  
34:     }  
35:     return result;  
36:    }  

The rest of the implementation is simple 'helper' methods. And it works - but with Unity, as usual, with some implications in terms of performance.

Of course, there are limitations. In particular, if a wrapped object has a property that can't be auto constructed, and is a reference type other than string - nothing will happen if that property is null. Now, for certain types, it will be relatively trivial to construct them, again, using reflection. So, if we had:

public List<IDomainObject> Associates { get; private set; }

Then, sure, we can construct an empty list easily enough. However, if we had instead:

public IEnumerable<IDomainObject> Associates { get; private set; }

This is rather more problematic. It's certainly quite easy to select any sub type of IEnumerable<T> and instantiate that - but if client objects ill advisedly have expectations of the concrete type of 'Associates' (say, for the sake of argument, it is an array and not a List<T> instance), it's going to be eminently breakable. Of course, we'd argue that expectations of the concrete type are improper on the part of a consumer; and, if you want an array, why not just use the construct: 'Associates.ToArray()'?

In terms of 'breakability', the OO purist side of me says 'tough' - but the real world is anything but pure or simple (or even predictable).

No comments: