The type IMyInterface does not have an accessible constructor."

May 13, 2008 at 9:02 PM
Guys,

I started using a Unity after reading all the requires docs. If I use a app.config to specify my interface (like ILogger) and class (UnityTest.ServiceInterfaces.TraceLogger) mapping, I get this excpetion
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity"
              type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
                 Microsoft.Practices.Unity.Configuration, Version=1.0.0.0,
                 Culture=neutral" />
  </configSections>
  <unity>
    <typeAliases>
      <!-- Lifetime manager types -->
      <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
      <typeAlias alias="external"  type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity" />
      <!-- User-defined type aliases -->

      <typeAlias alias="ILogger" type="UnityTest.ServiceInterfaces.ILogger, UnityTest" />
      <typeAlias alias="TraceLogger" type="UnityTest.ServiceImplementations.TraceLogger, UnityTest" />
    </typeAliases>
    <containers>
      <container>

        <types>
          <type type="ILogger" mapTo="TraceLogger" name="SushilLogger"/>
        </types>
      </container>
    </containers>
  </unity>
</configuration>

            IUnityContainer container = new UnityContainer();
            UnityConfigurationSection section
              = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            section.Containers.Default.Configure(container);           
            Application.Run(container.Resolve<Form1>());
+  [System.InvalidOperationException] {"The type ILoggerdoes not have an accessible constructor."} System.InvalidOperationException

But I use the hardcoded container
IUnityContainer container = new UnityContainer()
.RegisterType<ILogger, TraceLogger>();
Application.Run(container.Resolve<Form1>());
Its work fine (Form1 is requesting a ILogger using dependency attr)

Does any one know why it is a problem?
Any quickStart that comes with Unity deosn't use app.config.

Thanks
Sushil
May 13, 2008 at 10:09 PM
Your problem is that in the config file you give the type mapping a name. When you use the API, you don't.

You haven't shown the form, so I'll just assume you've either got a constructor parameter of type ILogger or a property. I'll use the constructor case for this explanation.

So, if your constructor looks like:

public Form1(ILogger logger) { ... }

The container will look for the default registration for ILogger. However, you haven't configured a default registration, you've only configured a named one. So there is no default, and it fails.

There are two (no four!) ways to do this.

First, you can remove the name from the type mapping in configuration: <type type="ILogger" mapTo="TraceLogger" />

Second, you can add an attribute on your constructor parameter saying which name to use to resolve the dependency:

public Form1([Dependency("SushiLogger")] ILogger logger) { ... }

Third, you can use the configuration API on the container to say which name to use to resolve the dependency:

container.Configure<InjectedMembers>()
    .ConfigureInjectionFor<Form1>(
        new InjectionConstructor(new ResolvedParameter(typeof(ILogger), "SushiLogger")));

Fourth, you can configure injection on Form1 in the config file (I'm not going to do an example of that one right now).

-Chris
May 13, 2008 at 11:54 PM

Thanks Chris, I realized name mapping was a problem but didn't know it was a problem, once I remove the name mapping (SushilLogger), it works fine.

Now I know the explanation. Really appreciate your response. I read the Unity doc and configuration schema that didn't mention anything like this.

Thanks

Sushil