I am using the Unity IoC container, and I need to intercept any calls to Resolve for a certain base interface, and run my own custom code to construct those types.
For completeness, I should add another answer that works under Unity 2, since my other answer no longer works. It is slightly more involved since you need to make a custom builder policy. Thanks to ctavares from the Unity project who provided lots of help on this thread in implementing this:
public class FactoryUnityExtension : UnityContainerExtension
{
private ICustomFactory factory;
private CustomFactoryBuildStrategy strategy;
public FactoryUnityExtension(ICustomFactory factory)
{
this.factory = factory;
}
protected override void Initialize()
{
this.strategy = new CustomFactoryBuildStrategy(factory, Context);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
Context.Policies.Set(new ParentMarkerPolicy(Context.Lifetime), new NamedTypeBuildKey());
}
}
public class ParentMarkerPolicy : IBuilderPolicy
{
private ILifetimeContainer lifetime;
public ParentMarkerPolicy(ILifetimeContainer lifetime)
{
this.lifetime = lifetime;
}
public void AddToLifetime(object o)
{
lifetime.Add(o);
}
}
public interface ICustomFactory
{
object Create(Type t);
bool CanCreate(Type t);
}
public class CustomFactoryBuildStrategy : BuilderStrategy
{
private ExtensionContext baseContext;
private ICustomFactory factory;
public CustomFactoryBuildStrategy(ICustomFactory factory, ExtensionContext baseContext)
{
this.factory = factory;
this.baseContext = baseContext;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = (NamedTypeBuildKey)context.OriginalBuildKey;
if (factory.CanCreate(key.Type) && context.Existing == null)
{
context.Existing = factory.Create(key.Type);
var ltm = new ContainerControlledLifetimeManager();
ltm.SetValue(context.Existing);
// Find the container to add this to
IPolicyList parentPolicies;
var parentMarker = context.Policies.Get(new NamedTypeBuildKey(), out parentPolicies);
// TODO: add error check - if policy is missing, extension is misconfigured
// Add lifetime manager to container
parentPolicies.Set(ltm, new NamedTypeBuildKey(key.Type));
// And add to LifetimeContainer so it gets disposed
parentMarker.AddToLifetime(ltm);
// Short circuit the rest of the chain, object's already created
context.BuildComplete = true;
}
}
}