I was wondering if anyone had any thoughts on extending MicroKernel/Windsor
to allow support for .NET 4's new Type Equivalence feature.  If you aren't
familiar with this, it allows the CLR to treat interfaces (as well as enums
and structs, I believe) that were defined in different assemblies as though
they are of the same type, as long as certain attributes have been applied
to them.  A good demonstration of the feature is available here:
http://blogs.msdn.com/mshneer/archive/2008/10/28/advances-in-net-type-system-type-equivalence-demo.aspx

I've done some basic tests to see how Windsor will react when a component is
registered using an interface defined in one assembly and resolved using an
equivalent type defined in another assembly.  I set up a solution containing
three projects: a host application and two DLLs.  None of the projects
references the other directly.  In each project I defined an identical
interface, ICommonInterface, to which I applied the required attributes to
enable type equivalence.  In the two DLL projects, I also provided
implementations of ICommonInterface.  In the host application, I loaded both
DLLs at runtime and used the fluent registration API to register all types
implementing ICommonInterface (using the host's version of it).  I then
tried to see if the container could resolve any instance of ICommonInterface
(again, using the host's version of it).

Here's what I found:

   - Attempting to call Resolve<ICommonInterface>() failed.  Looking through
   the code, it appears that this is because the different versions of
   ICommonInterface have different Type instances, so a lookup on the
   service2Handler dictionary in the DefaultNamingSubSystem (which uses Type as
   the key) will fail.
   - However, calling ResolveAll<ICommonInterface>() returned an instance of
   both registered classes.  I believe this is because it ultimately uses
   GetAssignableHandlers() on the naming subsystem, which uses
   Type.IsAssignableFrom() to check for a match instead of an equality check
   between the types.  Presumably, .NET 4 modified IsAssignableFrom() to
   respect type equivalence.

>From what I can tell, it seems to be possible to get MicroKernel to respect
type equivalence by providing a custom IEqualityComparer<Type>
implementation to the various dictionaries that use Type as a key in the
naming subsystem (and potentially a modification to GetHandlers(Type) to use
the same comparer instead of the == operator).  Here's the one I used:

    public class TypeEquivalenceComparer : EqualityComparer<Type>
    {
        public override bool Equals(Type x, Type y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (x == null || y == null) return false;
            return x.IsEquivalentTo(y);
        }

        public override int GetHashCode(Type obj)
        {
            return obj.GUID.GetHashCode();
        }
    }

Unfortunately, I haven't seen any good way of extending the
DefaultNamingSubSystem implementation to change just this behavior.  I had
to copy the entire body of the class to make my changes.  The main problem
is that a subclass can't replace the dictionaries with new ones using the
custom comparer because all of them are readonly and two of them are
private.

It would be a pretty simple change to the implementation to allow a custom
IEqualityComparer<Type> implementation to be provided as an optional
constructor argument.  If anyone thinks this is a good idea, I should be
able to supply a patch for it.

Does anyone have any opinions on this?

Thanks,
Michael Davis

-- 
You received this message because you are subscribed to the Google Groups 
"Castle Project Development List" group.
To post to this group, send email to castle-project-de...@googlegroups.com.
To unsubscribe from this group, send email to 
castle-project-devel+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/castle-project-devel?hl=en.

Reply via email to