How to resolve dependency in static class with Unity?

13,239

As you have already mentioned, Unity can't be used to resolve the class due to it being static. There are a few options for this. My personal favorite is using the Abstract Factory pattern. I tend to tweak the pattern just a tad to work well with DI.

The factory typically kind of looks like this:

/// <summary>
/// Creates an IMyDataContext instance
/// </summary>
public static class MyDataContextFactory
{
    /// <summary>
    /// The factory used to create an instance
    /// </summary>
    static Func<IMyDataContext> factory;

    /// <summary>
    /// Initializes the specified creation factory.
    /// </summary>
    /// <param name="creationFactory">The creation factory.</param>
    public static void SetFactory(Func<IMyDataContext> creationFactory)
    {
        factory = creationFactory;
    }

    /// <summary>
    /// Creates a new IMyDataContext instance.
    /// </summary>
    /// <returns>Returns an instance of an IMyDataContext </returns>
    public static IMyDataContext CreateContext()
    {
        if (factory == null) throw new InvalidOperationException("You can not create a context without first building the factory.");

        return factory();
    }
}

In your bootstrap process (where ever you setup your service registrations), you can initialize the factory to resolve your dependency.

MyDataContextFactory.SetFactory(() => this.Container.Resolve<IMyDataContext>());

Now in your extension method, you fetch a context.

public static class MyExtensions
{
    public static void MyExtensionMethod(this MyType myType)
    {
        MyDataContextFactory.CreateContext().DoAwesomeThing();
    }
}

Your Unity registration of the context, can handle the various different configurations of the service if there are conditions to resolving it. If there is the possibility that the context can be set by something other than Unity, that owner can just pass in a new delegate that the extension method will use.

I tend to avoid passing the containers themselves in to my factories, as that starts creeping tight-coupling of the containers to my app. If I'm going to pass anything in to the factory, i'd rather it be a factory delegate used to resolve via DI, than to pass the DI container in itself.

Share:
13,239

Related videos on Youtube

DaveDev
Author by

DaveDev

Updated on October 14, 2022

Comments

  • DaveDev
    DaveDev over 1 year

    I have the following extension method, which exists (naturally) in a static class.

    public static class MyExtensions
    {
        [Dependency]
        private static IMyDataContext _myDataContext { get; set; }
    
        public static void MyExtensionMethod(this MyType myType)
        {
            // do stuff
    
            _myDataContext.DoAwesomeThing();
        }
    }
    

    the _myDataContext object is null.

    Normally I'd use the UnityContainer to register the type, but as this is a static class, I can't.

    What do I need to instantiate _myDataContext so that it's not null when I need it?

  • Sriman Saswat Suvankar
    Sriman Saswat Suvankar over 6 years
    How can I make the above implementation generic? Like I want to pass any interface? IMyDataContext can be any interface. Can you provide any implementation?
  • Johnathon Sullinger
    Johnathon Sullinger over 6 years
    You would just make the SetContext and CreateContext methods generic. Your implementation would resolve <T> instead of IDataContext. You would have to store the Func<IDataContext as a Func<object> instead, and then attempt to cast it to Func<T> when you call CreateContext. Honestly though I'd evaluate using an extension method that needs to return data from a static class like this. DI the dependencies into your callers constructor, then provide the dependency in your extension method call as a method parameter.