Defining VirtualMethodInterceptor and HandlerAttribute in an xml config

Sep 8, 2011 at 7:51 PM

I’m trying to implement policy injection using a VirtualMethodInterceptor that calls handlers defined by Handler attributes. 

In the code below the ConfigFromCodeTest() works perfectly. Now I need to translate that configuration to a .config file,

but I can’t get it to work. What should my app.confg settings to be to mirror the ConfigFromCodeTest() configuration calls?

                                                                                                                 

As a side question, is there any way I can limit the use of LogCallBeginEndAttribute to only a VirtualMethodInterceptor? (beyond limiting to AttributeTargets.Class)

 

I’m using Unity 2.1.

 

Thanks for any help.

  
  
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace UnityTest
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method)]
    public class LogCallBeginEndAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return container.Resolve<LogCallBeginEndHandlerSimple>();
        }
    }

    public class LogCallBeginEndHandlerSimple : ICallHandler
    {
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            System.Diagnostics.Debug.WriteLine("Begin");
            IMethodReturn result = getNext().Invoke(input, getNext);
            System.Diagnostics.Debug.WriteLine("End");
            return result;
        }

        // order in which handler will be invoked
        public int Order { get; set; }
    }

    // [LogCallBeginEnd] // this works for ConfigFromCodeTest() too.
    public interface IDemoManager
    {
        string GetInfo(string info);
    }

    [LogCallBeginEnd]
    public class DemoManager : IDemoManager
    {
        // virtual for interceptor.
        public virtual string GetInfo(string info)
        {
            System.Diagnostics.Debug.WriteLine(string.Format("GetInfo() {0}", info));
            return "a result";
        }
    }


    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void ConfigFromCodeTest()
        {
            IUnityContainer container = new UnityContainer();

            container.AddNewExtension<Interception>();
            container.RegisterType<LogCallBeginEndHandlerSimple>();
            container.RegisterType<IDemoManager, DemoManager>();
            container.Configure<Interception>().SetInterceptorFor<DemoManager>(new VirtualMethodInterceptor());

            IDemoManager manager = container.Resolve<IDemoManager>();
            Assert.IsNotNull(manager);

            System.Diagnostics.Debug.WriteLine("Calling GetInfo()...");
            string s = manager.GetInfo("runtime config");
            Assert.IsNotNull(s);
            Assert.AreEqual("a result", s);

            // debug output:
            //   Calling GetInfo()...
            //   Begin
            //   GetInfo() runtime config
            //   End
        }

        [TestMethod]
        public void ConfigFromXmlTest()
        {
            IUnityContainer unity = new UnityContainer().LoadConfiguration("Demo");
            IDemoManager manager = unity.Resolve<IDemoManager>();
            Assert.IsNotNull(manager);

            System.Diagnostics.Debug.WriteLine("Calling GetInfo()...");
            string s = manager.GetInfo("xml config");
            Assert.IsNotNull(s);
            Assert.AreEqual("a result", s);

            // debug output:
            //   Calling GetInfo()...
            //   GetInfo() xml config
            //
            // How do I inject the LogCallBeginEndHandlerSimple???
        }
    }
}


App.config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />

    <container name="Demo">
      <extension type="Interception" />
      <register type="UnityTest.LogCallBeginEndHandlerSimple, UnityTest"/>
      <register type="UnityTest.IDemoManager, UnityTest" mapTo="UnityTest.DemoManager, UnityTest"/>
      <register type="UnityTest.DemoManager, UnityTest">
        <interceptor type="VirtualMethodInterceptor" />
        <!--I want to use attributes instead of policies.-->
        <!--<policyInjection/>   -->
      </register>
    </container>
  </unity>
</configuration>

Sep 13, 2011 at 8:38 AM

Hi,

I've stumbled on this thread and unfortunately, it seems that using policy is the only option here. Regarding with your second question, I'm not aware of any way on how it can be achieved. You might consider on having a custom behavior instead.

 

Noel Angelo Bolasoc
Avanade Software
Avanade, Inc.
Contact Us

Oct 17, 2011 at 4:27 PM
Edited Oct 17, 2011 at 4:32 PM

I figured this one out by accident. There is a disconnect between the fluid API and the XML config. In the xml you have to specify policy injection, in the fluid API you do not (I’m guess in happens transparently as a part of the SetInterceptorFor() call).

 

In the xml if you include the <policyInjection/> node, you do not actually need an <interception><policy> section (The point of the question was to avoid this). This is because <policyInection/> magically registers a “Microsoft.Practices.Unity.InterceptionExtension.AttributeDrivenPolicy” within Unity. So from the question above just change the xml to this and everything works

<!--l version="1.0" encoding="utf-8"--><?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>

  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />

    <container name="Demo">
      <extension type="Interception" />
      <register type="UnityTest.LogCallBeginEndHandlerSimple, UnityTest"/>
      <register type="UnityTest.IDemoManager, UnityTest" mapTo="UnityTest.DemoManager, UnityTest"/>
      <register type="UnityTest.DemoManager, UnityTest">
        <interceptor type="VirtualMethodInterceptor" />
        <!-- policyInjection registers a Microsoft.Practices.Unity.InterceptionExtension.AttributeDrivenPolicy no <policy> needed -->
        <policyInjection/>
      </register>
    </container>
  </unity>
</configuration>