Actually this could be good time to refactor DefaultNamingSubSystem away from storing services by strings, and store them by custom HandlerToken or something, that could be aware of the type equivalence.

Krzysztof


On 2010-03-22 20:06, Michael Davis wrote:
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.

--
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