InstanceWrapping (ObjectBuilder2?)

Nov 4, 2006 at 2:31 PM
Hi Guys,

I have a suggestion for a new Strategy (that proved itself usefull in a project I utilize OB).

InstanceWrapping

When doing DI over interfaces (public interface and internal realization) wrapping the result realizing instance in another class is a usefull extensionpoint.

example:

CoreLibrary contains public interface IValidationService (w/ Validate() method).
CoreLibrary also contains internal realization TheValidationService (w/ some basic validation logic).

There is also a Plugin1Library which needs to extend the validation behaviour in CoreLibrary (and has a dependency on CoreLibrary).

This is done by defining another realization of IValidationService (ExtendedValidationService, w/ extended validation logic) in the pluginLibrary.

and supplying a policy that tels the buildup-chain to wrap the created IValidationSevice in a new Instance of ExtendedValidationService. The ExtendedValidationService then could call the original one (doning the basic validation logic) and add new logic within its ValidateMethod.

In this example both the Plugin1Library and CoreLibrary can add configuration-logic to an ObjectBuilder facade.


Thus:


//TypeMap IValidationSevice -> TheValidationService
class CoreLibrary.TheValidationService: IValidationService
{
public void Validate(){AddError(1);}
}

//InstanceWrap IValidationSevice -> ExtendedValidationService.
class Plugin1Library.ExtendedValidationService : IValidationService
{
IValidationService _innerValidationService;
public ExtendedValidationService(IValidationService innerValidationService, etc, )
{
innerValidationService = innerValidationSevice;
}
public void Validate()
{
innerValidationService.Validate();
AddError(2);
}
}


Below my naive implementation of such a sevice. Assumes adding the Strategy before TypeMapping. this example is naive in the sense that it doesnt play nice with other strategies (such as singleton). but satisfied my needs.

public interface IInstanceWrappingPolicy : IBuilderPolicy
{
Type TypeToWrapWith{get;}
}

class InstanceWrappingStrategy : BuilderStrategy
{
public override object BuildUp(IBuilderContext context, Type typeToBuild, object existing, string idToBuild)
{
object buildedObject = base.BuildUp(context, typeToBuild, existing, idToBuild);

IInstanceWrappingPolicy instanceWrappingPolicy = context.Policies.Get<IInstanceWrappingPolicy>(typeToBuild, idToBuild);
if (null != instanceWrappingPolicy)
{
context.Policies.Set<ICreationPolicy>(new WrappedInstanceCreationPolicy(typeToBuild, buildedObject), instanceWrappingPolicy.TypeToWrapWith, idToBuild);
return context.HeadOfChain.BuildUp(context, instanceWrappingPolicy.TypeToWrapWith, null, idToBuild);
}

return buildedObject;
}

public class WrappedInstanceCreationPolicy : ICreationPolicy
{

Type typeToWrap;
object instanceOfType;

public WrappedInstanceCreationPolicy(Type typeToWrap, object instanceOfType)
{
this.typeToWrap = typeToWrap;
this.instanceOfType = instanceOfType;
}

/// <summary>
/// See <see cref="ICreationPolicy.SelectConstructor"/> for more information.
/// </summary>
public ConstructorInfo SelectConstructor(IBuilderContext context, Type typeToBuild, string idToBuild)
{
ConstructorInfo[] constructors = typeToBuild.GetConstructors();

if (constructors.Length > 0)
return constructors0;

return null;
}

/// <summary>
/// See <see cref="ICreationPolicy.GetParameters"/> for more information.
/// </summary>
public object[] GetParameters(IBuilderContext context, Type type, string id, ConstructorInfo constructor)
{
ParameterInfo[] parms = constructor.GetParameters();
object[] parmsValueArray = new objectparms.Length;

for (int i = 0; i < parms.Length; ++i)
{
Type parameterType = parmsi.ParameterType;
if (parameterType.IsAssignableFrom(typeToWrap))
{
parmsValueArrayi = instanceOfType;
}
else
{
parmsValueArrayi = context.HeadOfChain.BuildUp(context, parameterType, null, id);
}
}
return parmsValueArray;
}
}
}


Thanks!