Amir Popovich
Amir Popovich

Reputation: 29846

Dynamic IOC mapping with UnityContainer - How can I achieve?

I'm trying to create a smart IOC resolver using my UnityContainer that will receive information from a third party service as part of the resolving process.

If a config entry would typically look like this (I've create alias's for all types):

<type type="IMyInterface" mapTo="MyInstance">
    <lifetime type="Hierarchical" />
</type>

I would like to remove the mapTo, and provide it in runtime (per each relevant resolve request).

Now, I've tried doing this by creating a UnityContainerExtension and a BuilderStrategy and things got messy and work partially.

Since I only want to override the mapTo part, I guess that maybe I've gone to far.

So, how can I achieve that kind of functionality?
Is there anyway I can override the mapTo's getter\strategy?

Upvotes: 2

Views: 146

Answers (1)

Amir Popovich
Amir Popovich

Reputation: 29846

Ok so I found the hook.

First you need to create a BuilderStrategy that will lookup for the new mapping:

public class DynamicMappingBuildStrategy: BuilderStrategy
{
    public override void PreBuildUp(IBuilderContext context)
    {
        var policy = context.Policies.Get<IBuildKeyMappingPolicy>(context.BuildKey);

        if (policy != null)
        {
            context.BuildKey = policy.Map(context.BuildKey, context);
        }
        else
        {
            var oldMapping = context.BuildKey;
            var mappedType = DynamicMapper.GetMapping(oldMapping.Type);
            context.BuildKey = new NamedTypeBuildKey(mappedType, null);
            var lifetime = context.PersistentPolicies.Get<ILifetimePolicy>(oldMapping, true);

            if (lifetime != null)
            {
                context.PersistentPolicies.Set(lifetime, context.BuildKey);
            }
        }
    }
}

Then you need to create a UnityContainerExtension that will add the BuilderStrategy in the correct UnityBuildStage:

public class DynamicMappingBehaviorExtension : UnityContainerExtension
{
    protected override void Initialize()
    {
        this.Context.Strategies.AddNew<DynamicMappingBuildStrategy>(UnityBuildStage.TypeMapping);
    }
}

Then you need to configure your container to use the new extension:

<containers>
            <container>
                <extensions>
                    <add type="MyNamespace.DynamicMappingBehaviorExtension, MyDll" />
                </extensions>
....More configuration.....

And then you need to add your type mapping without a mapTo:

<type type="IVehicle">
    <lifetime type="Hierarchical" />
</type>

Upvotes: 2

Related Questions