I’m using the Provider pattern and Unity.
This is the typical provider implementation. I have SomeProvider as abstract base provider with the abstract methods as well as the logic to instantiate the defaultProvider.
public abstract class SomeProvider : ProviderBase
{
#region provider boilerplate
private const string PROVIDER_NAME = "someProvider";
private static volatile SomeProvider defaultProvider = null;
public static SomeProvider Provider
{
get { return defaultProvider; }
}
private static object providerLockObject = new object();
static SomeProvider()
{
LoadProvider();
}
private static void LoadProvider()
{
if (defaultProvider == null)
{
lock (providerLockObject)
{
if (defaultProvider == null)
{
// exception handling omitted for brevity
var section = ConfigurationManager.GetSection(PROVIDER_NAME)
as BaseProviderConfigurationSection;
defaultProvider = ProvidersHelper.InstantiateProvider(
section.Providers[section.DefaultProvider], typeof(SomeProvider)) as SomeProvider;
}
}
}
}
protected SomeProvider() { }
#endregion
#region abstract methods
public abstract bool DoSomething();
#endregion
}
Here is the ASomeProvider that implements SomeProvider. Note that ASomeProvider has dependancy ADependency but SomeProvider does not.
public class ASomeProvider : SomeProvider
{
#region provider boilerplate
private string name;
public override string Name
{
get { return name; }
}
public override void Initialize(string name, NameValueCollection config)
{
this.name = name;
base.Initialize(name, config);
}
#endregion
// Provider pattern needs parameterless ctor and calls this
public ASomeProvider() { }
// constructor injection
public ASomeProvider(ADependency aDependency)
{
this.ADependency = aDependency;
}
[Dependency]
public SomeDependency ADependency { get; set; }
#region methods
public override void DoSomething()
{
// do something
}
#endregion
}
class SomeDependency {}
I use the ASomeProvider in a business layer as follows:
public class SomeBusinessLayer
{
public SomeProvider someProvider;
public SomeBusinessLayer(SomeProvider someProvider)
{
this.someProvider = someProvider;
}
#region methods
public bool DoSomethingWrapper()
{
return someProvider.DoSomething();
}
#endregion
}
I have the BusinessLayerFactory factory for wiring up objects using Unity and returning objects as follows:
public static class BusinessLayerFactory
{
private static UnityContainer container;
private static void WireUp()
{
container = new UnityContainer();
container.RegisterInstance(SomeProvider.Provider);
container.RegisterInstance(new SomeDependency());
container.RegisterType<SomeBusinessLayer>(new ContainerControlledLifetimeManager());
}
public static SomeBusinessLayer SomeBusinessLayer_Unity
{
get
{
return container.Resolve<SomeBusinessLayer>();
}
}
public static SomeBusinessLayer SomeBusinessLayer_Self()
{
var asomeProvider = SomeProvider.Provider as ASomeProvider;
if (asomeProvider != null && asomeProvider.ADependency == null)
asomeProvider.ADependency = new ADependency();
return new SomeBusinessLayer(SomeProvider.Provider);
}
}
The problem that I have is that when I resolve to get SomeBusinessLayer, the someProvider has its dependency ADependency as null.
var someBusinessLayer = BusinessLayerFactory.SomeBusinessLayer_Unity;
((ASomeProvider)someBusinessLayer.someProvider).ADependency is null.
The reason for it is that the Provider pattern uses the helper method ProvidersHelper.InstantiateProvider(ProviderSettings providerSettings, Type type) to instantiate the default provider and not through Unity’s Resolve<T>() method.
I can think of doing this without Unity as shown in SomeBusinessLayer_Self where I new ADependency if null but just wondering if and how Unity handles this.
Method injection or Ctor injection is fine by me.
How do I fix this and have Unity and Provider pattern work together? My main reason for using Unity is to wire up objects in the factory.
I’m not using MVC.
UPDATE:
To fix this:. hat-tip to @seth-flowers
I could not figure out a way without an explicit cast container.BuildUp<ASomeProvider>(aSomeProvider).
container.RegisterInstance(new SomeDependency());
//this does not build up the object with dependency
container.BuildUp(SomeProvider.Provider);
//this works and does build up
var aSomeProvider = SomeProvider.Provider as ASomeProvider;
if(aSomeProvider != null)
container.BuildUp<ASomeProvider>(aSomeProvider);
//compile error
container.BuildUp<ASomeProvider>(SomeProvider.Provider);
container.RegisterInstance(SomeProvider.Provider);
container.RegisterType<SomeBusinessService>(new ContainerControlledLifetimeManager());
Couldn’t you use UnityContainer.BuildUp in your
BusinessLayerFactory.WireUpmethod, in order to flesh out the dependencies on yourSomeProvider.Providerinstance? Your object would still be constructed through your provider implementation, but would have dependency injection through unity.For instance:
The docs for BuildUp state the following: