register mapTo attribute not recognizing alias value with namespace/assembly hints...

Jun 10, 2012 at 5:21 AM
Edited Jun 10, 2012 at 5:42 AM
Hello everyone,

I am having an issue using aliases for the mapTo value in a type registration when the alias is relying on namespace and assembly element lookup

using the following configuraion, I get an InvalidOperationException "The type name or alias Service could not be resolved. Please check your configuration file and verify this type name."
 <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <namespace  name="DemoUnity.Utility" />
    <assembly name="DemoUnity" />
    <alias alias="IService" type="IService[,]" />
    <alias alias="Service" type="DemoService" />
    <container>
      <register mapTo="Service" 
                type="IService[int, string]" name="Demo Service" />
      <register type="DemoRepo">
        <constructor>
          <param dependencyName="Demo Service" name="service" />
        </constructor>
      </register>
    </container>
  </unity>


but if I put the assembly qualified name in the alias it works:
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <namespace  name="DemoUnity.Utility" />
    <assembly name="DemoUnity" />
    <alias alias="IService" type="IService[,]" />
    <alias alias="Service" type="DemoUnity.Utility.DemoService, DemoUnity" />
    <container>
      <register mapTo="Service" 
                type="IService[int, string]" name="Demo Service" />
      <register type="DemoRepo">
        <constructor>
          <param dependencyName="Demo Service" name="service" />
        </constructor>
      </register>
    </container>
  </unity>  

The IService generic and the DemoService concrete are in the same namespace, assembly.

Why is the alias type resolving, but the mapTo is not?

this is my code:
using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Collections.Specialized;

namespace DemoUnity.Utility
{
    public interface IService<T1, T2>
    {

    }

    public class DemoService : IService<int, string> { }

    public class DemoRepo
    {
        public IService<int, string> Service
        {
            get;
            set;
        }
        public DemoRepo(IService<int, string> service)
        {
            Service = service;
        }
    }
}

namespace DemoUnity
{
    using DemoUnity.Utility;

    class Program
    {
        static void Main(string[] args)
        {
            var container = new UnityContainer().LoadConfiguration();
            var repo = container.Resolve<DemoRepo>();
            Console.ReadLine();
        }
    }
}
Jun 10, 2012 at 6:22 AM
Edited Jun 10, 2012 at 6:23 AM

The short answer is that aliases must be fully qualified types.  From Specifying Types in the Configuration File: "An alias is simply a shorthand name that will be replaced with the full type name...

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="MyAlias" type="full type name" />
    ...
</unity>" 

And from AliasElement TypeName Property: "The fully qualified name this alias refers to".

The assembly and namespace are used as the last option in trying to resolve a type.  They attempt to resolve a concrete type directly based on the mapTo type (in this case) and possible combinations of assemblies and namespaces.  

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jun 10, 2012 at 1:23 PM

huh????

Why does the interface alias resolve, but the concrete does not?

That being said, using the simple concrete name in the mapTo does resolve against the assembly/namespace elements:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <namespace  name="DemoUnity.Utility" />
    <assembly name="DemoUnity" />
    <alias alias="IService" type="IService[,]" />
    <container>
      <register mapTo="DemoService" 
                type="IService[int, string]" name="Demo Service" />
      <register type="DemoRepo">
        <constructor>
          <param dependencyName="Demo Service" name="service" />
        </constructor>
      </register>
    </container>
  </unity>  

And this is adequate

 

 

Jun 10, 2012 at 2:48 PM

> Why does the interface alias resolve, but the concrete does not?

That does appear confusing.  Actually, in this case the alias is not being used!  Unity is looking up the type by searching through the assemblies and namespaces.   The resolution of IService[int, string] actually uses the generic shorthand syntax and not the alias.  You can see this for yourself by changing the configuration file to not use an alias (but leave the DemoService type in mapTo):

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <namespace  name="DemoUnity.Utility" />
    <assembly name="DemoUnity" />
    <container>
      <register mapTo="DemoService"
                type="IService[int, string]" name="Demo Service" />
      <register type="DemoRepo">
        <constructor>
          <param dependencyName="Demo Service" name="service" />
        </constructor>
      </register>
    </container>
  </unity>

The type DemoRepo should be able to be resolved with all dependent types injected without an alias.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com