interceptors -error

Oct 17, 2012 at 7:26 PM

I am trying to intercept a WCF client. But the Unity interceptor does not seem to work.

1) I am not getting a call to the proxy. 2) I did not know how to link the attribute to the container 3) In AddPolicy what is the name attribute - Here I used the function to intercept - GetXml.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Method)] public class GetXmlCallHandlerAttribute : HandlerAttribute { public GetXmlCallHandlerAttribute(){}

    public override ICallHandler CreateHandler(IUnityContainer ignored)
    {
      return new GetXmlTestCallHandler();
    }
  }

  public class GetXmlTestCallHandler : ICallHandler
  {
    public int Order { get; set; }  

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
      IMethodReturn msg;
      Object returnValue = XElement.Load("../../Resources/a1.xml");
      Object[] outputs = null;
      msg = input.CreateMethodReturn(returnValue, outputs);
      return msg;        
    }
    //public delegate IMethodReturn InvokeHandlerDelegate(IMethodInvocation input,
    //                          GetNextHandlerDelegate getNext);

    //public delegate InvokeHandlerDelegate GetNextHandlerDelegate();

  } 
class SendDataTest
{
    public void GetXmlTest()
    {

      IUnityContainer container = new UnityContainer();
      ICallHandler myInterception = new GetXmlTestCallHandler();    

      container.AddNewExtension<Interception>();
      container.RegisterType<SendData>(new Interceptor(new TransparentProxyInterceptor()));
      container.Configure<Interception>().AddPolicy("GetXml").AddCallHandler(myInterception);
      SendData target = container.Resolve<SendData>();
      XElement expected = null; // TODO: Initialize to an appropriate value
      XElement actual;
      actual = target.GetXml();
      Assert.AreEqual(expected, actual);
      Assert.Inconclusive("Verify the correctness of this test method.");
    }
}
Oct 18, 2012 at 4:23 AM

If you are using TransparentProxyInterceptor then SendData will need to implement an interface or inherit from MarshalByRefObject.  Since you are registering and resolving the concrete SendData class then it will need to inherit from MarshalByRefObject.  Since you didn't post the SendData class I'm not sure if that is true.  If SendData is a WCF ClientBase<T> or ChannelFactory<T> then it doesn't inherit from MarshalByRefObject so you would need to use interfaces or virtual methods.

I'm assuming you are applying your custom attribute.  If that is the case then you should add a CustomAttributeMatchingRule to the policy and also add PolicyInjectionBehavior to the registration.  Here is a contrived example based on your code (with a string return value instead of XElement) using MarshalByRefObject:

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Method)]
    public class GetXmlCallHandlerAttribute : HandlerAttribute
    {
        public GetXmlCallHandlerAttribute() { }

        public override ICallHandler CreateHandler(IUnityContainer ignored)
        {
            return new GetXmlTestCallHandler();
        }
    }

    public class GetXmlTestCallHandler : ICallHandler
    {
        public int Order { get; set; }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            IMethodReturn msg;
            msg = input.CreateMethodReturn("<abc>def</abc>");
            return msg;
        }
    } 

    class Program
    {
        public static void GetXmlTest()
        {
            IUnityContainer container = new UnityContainer();

            container.AddNewExtension<Interception>();

            CustomAttributeMatchingRule matchingRule = new CustomAttributeMatchingRule(typeof(GetXmlCallHandlerAttribute), true);
            ICallHandler myInterception = new GetXmlTestCallHandler();
            
            container.Configure<Interception>()
                .AddPolicy("GetXml")
                .AddCallHandler(myInterception)
                .AddMatchingRule(matchingRule);

            container.RegisterType<SendData>(
                new Interceptor(new TransparentProxyInterceptor()), 
                new InterceptionBehavior<PolicyInjectionBehavior>());

            var target = container.Resolve<SendData>();
            var actual = target.GetXml();

            var target2 = container.Resolve<SendDataNoIntercept>();
            var actual2 = target2.GetXml();
        }

        static void Main(string[] args)
        {
            GetXmlTest();
        }
    }

    public class SendData : MarshalByRefObject
    {
        [GetXmlCallHandler]
        public string GetXml()
        {
            return "<abc>xyz</abc>";
        }
    }

    public class SendDataNoIntercept : MarshalByRefObject
    {
        public string GetXml()
        {
            return "<abc>xyz</abc>";
        }
    }

The interface example is similar except that we register and resolve an interface:

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Method)]
    public class GetXmlCallHandlerAttribute : HandlerAttribute
    {
        public GetXmlCallHandlerAttribute() { }

        public override ICallHandler CreateHandler(IUnityContainer ignored)
        {
            return new GetXmlTestCallHandler();
        }
    }

    public class GetXmlTestCallHandler : ICallHandler
    {
        public int Order { get; set; }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            IMethodReturn msg;
            msg = input.CreateMethodReturn("<abc>def</abc>");
            return msg;
        }
    } 

    class Program
    {
        public static void GetXmlTest()
        {
            IUnityContainer container = new UnityContainer();

            container.AddNewExtension<Interception>();

            CustomAttributeMatchingRule matchingRule = new CustomAttributeMatchingRule(typeof(GetXmlCallHandlerAttribute), true);
            ICallHandler myInterception = new GetXmlTestCallHandler();
            
            container.Configure<Interception>()
                .AddPolicy("GetXml")
                .AddCallHandler(myInterception)
                .AddMatchingRule(matchingRule);

            container.RegisterType<ISendData, SendData>(
                new Interceptor(new TransparentProxyInterceptor()), 
                new InterceptionBehavior<PolicyInjectionBehavior>());

            container.RegisterType<ISendData, SendDataNoIntercept>("NoIntercept",
                new Interceptor(new TransparentProxyInterceptor()),
                new InterceptionBehavior<PolicyInjectionBehavior>());

            var target = container.Resolve<ISendData>();
            var actual = target.GetXml();

            var target2 = container.Resolve<ISendData>("NoIntercept");
            var actual2 = target2.GetXml();
        }

        static void Main(string[] args)
        {
            GetXmlTest();
        }
    }

    public interface ISendData
    {
        string GetXml();
    }

    public class SendData : ISendData
    {
        [GetXmlCallHandler]
        public string GetXml()
        {
            return "<abc>xyz</abc>";
        }
    }

    public class SendDataNoIntercept : ISendData
    {
        public string GetXml()
        {
            return "<abc>xyz</abc>";
        }
    }

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