0

I've been looking through examples and documentation for Autofac, and can't see to get this working.

We have a helper class, Core.Helpers.Tokens with a property set up like this:

namespace Core.Helpers
{
    public static class Tokens
    {
        private static IConfigurationManager ConfigurationManager;

        public static string GetToken()
        {
            var sessionTokenName = ConfigurationManager.GetAppSetting("SessionTokenName");
            return (string) HttpContext.Current.Session[sessionTokenName];
        }
    }
}

The configuration is designed like this:

namespace Core.Config
{
    public interface IConfigurationManager
    {
        //...
    }

    public class WebConfigConfigurationManager : IConfigurationManager
    {
        //...
    }
}

In our MVC Web app (which references and uses Core.Helpers, Startup.cs I'm trying to register IConfigurationManager for property injection.

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var builder = new ContainerBuilder();

        // REGISTER CONTROLLERS SO DEPENDENCIES ARE CONSTRUCTOR INJECTED
        builder.RegisterControllers(typeof(MvcApplication).Assembly);
        builder.RegisterModule<AutofacWebTypesModule>();
        builder.RegisterFilterProvider();
        builder.RegisterType<WebConfigConfigurationManager>().As<IConfigurationManager>().PropertiesAutowired();

        RegisterTypes(builder);

        // BUILD THE CONTAINER
        var container = builder.Build();
        var webConfig = container.Resolve<IConfigurationManager>();

        // REPLACE THE MVC DEPENDENCY RESOLVER WITH AUTOFAC
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

        // REGISTER WITH OWIN
        app.UseAutofacMiddleware(container);
        app.UseAutofacMvc();
    }

When the web code calls GetToken, ConfigurationManager is null. What am I missing?

M Kenyon II
  • 4,136
  • 4
  • 46
  • 94

2 Answers2

1

One error is that your Tokens.ConfigurationManager is a private field, whereas property injection works with public properties.

Also, it must be an instance property, not static. So in the end it should be

public IConfigurationManager ConfigurationManager{get;set;}

But that would mean you'd also have to inject a Tokens instance, and that would make no longer a static helper class, you'll have to do some redesign, there are some options:

  1. If you have an IConfigurationManager instance everywhere you expect to call GetTokens from you can pass that in as an input parameter to GetTokens()
  2. You promote this static helper to a dependency (e.g. ITokenService ? ) that will be injected to everywhere it's needed. Instead of making it static, you can use Autofac lifetime management to make it a singleton. (Probably the best solution)
  3. The worst solution, but the smallest change, one that works without having to give up this being a static helper class, is to make the property use the DependencyResolver instead of injection, something like:

    private static IConfigurationManager ConfigurationManager{ get { return DependencyResolver.Current.GetService();} }

Loonquawl
  • 1,058
  • 1
  • 11
  • 16
  • Okay, I can see it needing to be public. But you cannot declare instance members in a static class. – M Kenyon II Jun 23 '17 at 15:18
  • Why would the 3rd be the worst? – M Kenyon II Jun 23 '17 at 15:47
  • The third solution is essentially giving up DI and downgrading to using Service Locator, which has many disadvantages, and some even consider it an anti-pattern. https://stackoverflow.com/questions/1557781/whats-the-difference-between-the-dependency-injection-and-service-locator-patte – Loonquawl Jun 23 '17 at 15:55
0

You are resolving IConfigurationManager, You should be resolving WebConfigConfigurationManager.

If you have 5 classes that utilize IConfigurationmanager, resolving the interface does not tell autoface which concrete class you are wanting to utilize which has this interface.

Scornwell
  • 597
  • 4
  • 19
  • When I try to resolve `var webConfig = container.Resolve();` I get: An exception of type 'Autofac.Core.Registration.ComponentNotRegisteredException' occurred in Autofac.dll but was not handled in user code Additional information: The requested service 'Clark.Chains.Core.Config.WebConfigConfigurationManager' has not been registered. – M Kenyon II Jun 23 '17 at 17:50