issue with Class<T> : Interface <T>

Oct 3, 2014 at 5:46 PM
this worked fine in 3.0 but is saying it's not registered in 3.5 even though it is.

interface
    public interface IMessagingClientService<T>
class
  internal class MessagingClientService<T> : IMessagingClientService<T>
the registration is, notice the no T so it should resolve any IMessagingClientService to this class IMessagingClientService<>

when trying to resolve the type is IMessagingClientService<int>

what I think is happening, is in 3.0 the IsRegistered used to use Type.Equals for ISRegistered
  IL_0001:  callvirt   instance class [mscorlib]System.Type Microsoft.Practices.Unity.ContainerRegistration::get_RegisteredType()
  IL_0006:  ldarg.0
  IL_0007:  ldfld      class [mscorlib]System.Type Microsoft.Practices.Unity.UnityContainerExtensions/'<>c__DisplayClass1'::typeToCheck
  IL_000c:  call       bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
                                                               class [mscorlib]System.Type)
  IL_0011:  brfalse.s  IL_0025
in 3.5 it doesn't
  IL_0001:  callvirt   instance class [System.Runtime]System.Type Microsoft.Practices.Unity.ContainerRegistration::get_RegisteredType()
  IL_0006:  ldarg.0
  IL_0007:  ldfld      class [System.Runtime]System.Type Microsoft.Practices.Unity.UnityContainerExtensions/'<>c__DisplayClass1'::typeToCheck
  IL_000c:  bne.un.s   IL_0020
Oct 3, 2014 at 6:07 PM
Can you post a more complete example including the registration code?

Thanks.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Oct 3, 2014 at 6:30 PM
its the IsRegistered that is broken
the Resolve works but I check IsRegistered before calling Resolve.
look at the IL code I posted the 3.5 is using bne.un.s instead of calling Type.Equals.
Oct 4, 2014 at 3:48 PM
Edited Oct 7, 2014 at 4:30 AM
I don't see any changes to the source code and the IL I'm looking at for UnityContainerExtensions.IsRegistered differs from what is posted.

The following code fails in Unity 2.1, 3.0, 3.5, and pre-release:
container.RegisterType(typeof(Common.IMessagingClientService<>), typeof(Common.MessagingClientService<>));

bool isRegistered = false;
isRegistered = container.IsRegistered<Common.IMessagingClientService<int>>();
Debug.Assert(isRegistered);

While the resolve succeeds. So I'm still not 100% sure what the exact scenario is.

The following comments might not apply to your situation but I include them for future readers (and if you find it interesting then great).

IsRegistered doesn't necessarily indicate whether an item can be resolved. e.g. in the case of a concrete class:
    public class MyClass
    {
    }

bool isRegistered = container.IsRegistered<MyClass>();
var myClass = container.Resolve<MyClass>();

In the above example isRegistered returns false while a MyClass instance is returned.

Another scenario is a custom Unity Container Extension could also allow interfaces to be mapped such that IsRegistered returns false but the extension figures out the mapping and resolves the correct class (not saying this would be a good thing just that it's possible).

According to this thread IsRegistered is not recommended to be used extensively.


~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Jan 14, 2015 at 5:17 PM
This looks like a bug in the IsRegistered method and I have detailed it out here. In short when the registered type is a generic type then then the type should be compared against a generic type definition of the interface that is trying to be checked for.

If a container can Resolve a particular type then it should also be able to return that it IsRegistered.
Have submitted a pull request for this