CallHandlers for different interface implementations - feature or bug?

Dec 9, 2008 at 11:13 PM
Hi All,

I failed miserably trying attach different call handlers to two different implementation of the same interface and would greatly appreciate any help in the matter.

I distilled my problem to the simplest following example.

I created the following interface:

    public interface Interface
    {
        string Greeting(string name);
    }
 
and registered in the container two implementations of it ander names "Hello" and Hi:

    public class Hello: Interface
    {
        public string Greeting(string name)
        {
            return "Hello " + name;
        }
    }
  
    public class Hi: Interface
    {
        public string Greeting(string name)
        {
            return "Hi " + name;
        }
    }

I defined two different ICallHandler implementations (HandlerFanny and HandlerFreddy) that modify the "name" parameter of the Greeting method by adding some specific names ("Fanny" and "Freddy" respectively) to the "name" parameter of the Greeting method.

Here is Invoke method for HandlerFanny:

  public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
  {
       input.Arguments[0] = (string)input.Arguments[0]+"Fanny";
       IMethodReturn result = getNext().Invoke(input, getNext);
       return result;
  }

and for HandlerFreddy:

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            input.Arguments[0] = (string)input.Arguments[0] + "Freddy";
            IMethodReturn result = getNext().Invoke(input, getNext);
            return result;
        }


Then I tried to attach HandlerFanny to Hi  and HandlerFreddy to Hello implemetation of the Interface: 

     IUnityContainer GetCodeInteceptionContainer()
      {
            IUnityContainer container = new UnityContainer()
                .RegisterType<Interface, Hi>("Hi", new InjectionMember[] { })
                .RegisterType<Interface, Hello>("Hello", new InjectionMember[] { })
                .AddNewExtension<Interception>()
            .Configure<Interception>()
                .SetInterceptorFor(typeof(Interface), "Hi", new TransparentProxyInterceptor())
                .AddPolicy("Meet Fanny")
                .AddMatchingRule(typeof(MemberNameMatchingRule), "Hi", new InjectionMember[] { new InjectionConstructor("Greeting", true) })
                 //.AddMatchingRule(new TypeMatchingRule("Lib.Hi"))
                .AddCallHandler(new TestSupport.HandlerFanny(1))
            .Interception
                .SetInterceptorFor(typeof(Interface), "Hello", new TransparentProxyInterceptor())
                .AddPolicy("Meet Freddy")
                .AddMatchingRule(typeof(MemberNameMatchingRule), "Hello", new InjectionMember[] { new InjectionConstructor("Greeting", true) })
                //.AddMatchingRule(new TypeMatchingRule("Lib.Hello"))
                .AddCallHandler(new TestSupport.HandlerFreddy(1))
            .Interception
       .Container;
       return container;
   }

I expected that the calls to Greeting method would result in "Hi Fanny" and "Hello Freddy" as in the following unit test:

        [TestMethod]
        public void ShouldInterceptCallToRightClass()
        {
            IUnityContainer container = GetInteceptionContainer(true);
            Interface hiInstance = container.Resolve<Interface>("Hi");
            Assert.AreEqual("Hi Fanny", hiInstance.Greeting(""));
            Interface helloInstance = container.Resolve<Interface>("Hello");
            Assert.AreEqual("Hello Freddy", helloInstance.Greeting(""));
        }

However, the test failed: Assert.AreEqual failed. Expected:<Hi Fanny>. Actual:<Hi FannyFreddy>.

As one can see both handlers somehow attached to the Greeting method in both Hi and Hello implementations of the Interface although I specifically tried to attach different handlers to different implementations via specifying different build keys in the calls to SetInterceptorFor method.

If I uncomment additional TypeMatchingRule-s in the configuration code the unit test passes just fine.

Is it a bug in Unity or am I missing something here?

Thanks in advance for any  help on the subject,
SYS.
Dec 10, 2008 at 2:43 PM
I just copied your code and everything works fine.  In fact, if I uncomment the TypeMatchingRule, the output of the Greeting method was Hi FannyFreddy.  You could send me your solution, you might just be missing a small thing.


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com

Dec 10, 2008 at 3:52 PM
Hi Sarah,
 
Thanks a lot for the quick response. I e-mailed the solution to you. Compared to the one I posted on CodePlex it has couple macros defined:
 
#define __MEET_FREDDY__
#define __MEET_FANNY__
that allow to enable interceptions separately. The code I posted corresponds to the case when both macros are defined.
 
I am using standalone unity block and VS2005.
 
Could you possibly send me your solution so I could play with it and try to figure out what the difference is?
 
Kind regards,
SYS.
 
Dec 11, 2008 at 5:32 AM
Edited Dec 11, 2008 at 5:40 AM
I've sent you my working solution and I'm currently checking out the one you sent to me. 


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com
Dec 11, 2008 at 6:06 AM
Edited Dec 11, 2008 at 6:38 AM
Hi, sorry I think we had a misunderstanding.  The correct solution to this is really uncommenting the TypeMatchingRule.   I assume the problem might be related to this post.  http://www.codeplex.com/entlib/Thread/View.aspx?ThreadId=8928


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com
Dec 11, 2008 at 1:16 PM
Thanks for the response, but I think my problem is different.

Indeed, I try to match a method in a class implementing an interface using policy with MemberNameMatchingRule. But the similarity ends here. In the thread you posted the rule maches twice: once on the interace method and once on the implementing class method resulting in call handler being called twice. That was recognized as a bug in Enterprise Library 3.0. I can mimic that problem by defining only one of the macros - either
 
#define __MEET_FREDDY__

or

#define __MEET_FANNY__

and this works just fine - the appropriate call handler is called only once as it supposed to, so apparently it was fixed in the Enterprise Library 4.1/Unity 1.2 that I am using

The problem starts when I define both macros and therefore have two policies, each one supposed to match only its own implementaion of the same interface. However, each policy also matches another implementation of the interface that was supposed to be matched by another policy.
Dec 12, 2008 at 7:13 PM
Just wanted to let know that my question is still unanswered. I would greatly appreciate if some one would comment on the subject - did I do something wrong or this is a bug in unity?

Dec 13, 2008 at 3:02 AM
Edited Dec 15, 2008 at 6:33 AM
Hi, sorry for the late reply.  My point was it seems that it has something to do with using membername matching rules with interfaces.  It does seem like a bug to me.  Anyway, I'm having some trouble with my machine right now so I can't perform debugging but I'll let you know as soon as I've verified that this is a bug.


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com

Dec 15, 2008 at 7:49 AM
I personally think that this is a bug because even if I used a different interface for the Hello class but have the same method Greeting(string name), the 2 handlers still get executed.  
You can use the typematchingrule as a workaround for the meantime.  I'll just have this reported to Microsoft and give you an update.  


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com
Dec 15, 2008 at 12:35 PM
Thanks!
Dec 17, 2008 at 5:56 AM
I've already added this item in the issue tracker.  http://www.codeplex.com/unity/WorkItem/View.aspx?WorkItemId=3489


Sarah Urmeneta
Global Technology & Solutions
Avanade, Inc.
entlib.support@avanade.com