EL 4.1 InterfaceInterceptor - Problem?

Topics: Enterprise Library Core, Policy Injection Application Block
Jan 16, 2009 at 2:56 AM
If anyone here knows what's the right way to make use of the new interface interception features in EL 4.1, could you please help me out?

I've been trying to make use of the built-in caching and validation call handlers, intercepted by the InterfaceInterceptor. This doesn't seem to be working as expected. However, simply switching the Interceptor to the TransparentProxyInterceptor seems to do the trick. I've also logged this here in the Issue Tracker.

Is there anything extra that I need to do from a configuration perspective? The sample below does not have any app.config file.
When run as-is, no validation exceptions are thrown. But when you change the InterfaceInterceptor to TransparentProxyInterceptor, all the validation exceptions fire correctly. For the equivalent caching interception source code, see this issue.

namespace ValidationBugDemo
{
    using System;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers;
    using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.InterceptionExtension;


    public class Bar
    {
        [NotNullValidator]
        [StringLengthValidator(5, 10)]
        public string StringProperty { get; set; }
        [RangeValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive)]
        public int NumberProperty { get; set; }
        public override string ToString()
        {
            return string.Format("String={0}; Number={1}", StringProperty, NumberProperty);
        }
    }
    
    public interface IFoo
    {
        [ValidationCallHandler]
        void EatString(
            [NotNullValidator]
            [StringLengthValidator(5, 10)]
            string something);
        [ValidationCallHandler]
        void EatObject(
            [NotNullValidator]
            [ObjectValidator]
            Bar something);
        [ValidationCallHandler]
        void EatNumber(
            [RangeValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive)]
            int something);
    }

    public class Foo : IFoo
    {
        public void EatString(string something)
        {
            Console.WriteLine(string.Format("EatString({0})", something));
        }

        public void EatObject(Bar something)
        {
            Console.WriteLine(string.Format("EatObject({0})", something));
        }

        public void EatNumber(int something)
        {
            Console.WriteLine(string.Format("EatNumber({0})", something));
        }
    }


    public class Program
    {
        static void Main(string[] args)
        {
            IUnityContainer _container = new UnityContainer();

            _container
                .AddNewExtension<interception />();            
                

            IConfigurationSource configSource = ConfigurationSourceFactory.Create();
            PolicyInjectionSettings settings = configSource.GetSection(PolicyInjectionSettings.SectionName) as PolicyInjectionSettings;
            if (settings != null)
            {
                settings.ConfigureContainer(_container, configSource);
            }

            _container.Configure<interception />()
                .SetInterceptorFor<ifoo />(new InterfaceInterceptor());

            _container.RegisterType<ifoo, />();
            IFoo foo = _container.Resolve<ifoo />();


            Action<action /> test = new Action<action />((action) => 
            {
                try
                {
                    action();
                    Console.WriteLine("No exception thrown!");
                }
                catch (Exception e)
                {
                    Console.WriteLine(string.Format("{0}: {1}", e.GetType(), e.Message));
                }
            });

            test(() => foo.EatString(null));
            test(() => foo.EatString("123"));
            test(() => foo.EatString("12345678901234567890"));
            test(() => foo.EatNumber(-1));
            test(() => foo.EatNumber(0));
            test(() => foo.EatNumber(1));
            test(() => foo.EatNumber(15));
            test(() => foo.EatObject(null));
            test(() => foo.EatObject(new Bar() { NumberProperty = 0, StringProperty = null }));
            test(() => foo.EatObject(new Bar() { NumberProperty = 8, StringProperty = "123" }));

            Console.ReadLine();
        }
    }
}

Jan 16, 2009 at 3:01 AM

Seems like the editor ate some bits. Reposting source code here: 

namespace ValidationBugDemo
{
    using System;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers;
    using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.InterceptionExtension;

    public class Bar
    {
        [NotNullValidator]
        [StringLengthValidator(5, 10)]
        public string StringProperty { get; set; }
        [RangeValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive)]
        public int NumberProperty { get; set; }
        public override string ToString()
        {
            return string.Format("String={0}; Number={1}", StringProperty, NumberProperty);
        }
    }
   
    public interface IFoo
    {
        [ValidationCallHandler]
        void EatString(
            [NotNullValidator]
            [StringLengthValidator(5, 10)]
            string something);
        [ValidationCallHandler]
        void EatObject(
            [NotNullValidator]
            [ObjectValidator]
            Bar something);
        [ValidationCallHandler]
        void EatNumber(
            [RangeValidator(5, RangeBoundaryType.Inclusive, 10, RangeBoundaryType.Inclusive)]
            int something);
    }

    public class Foo : IFoo
    {
        public void EatString(string something)
        {
            Console.WriteLine(string.Format("EatString({0})", something));
        }

        public void EatObject(Bar something)
        {
            Console.WriteLine(string.Format("EatObject({0})", something));
        }

        public void EatNumber(int something)
        {
            Console.WriteLine(string.Format("EatNumber({0})", something));
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            IUnityContainer _container = new UnityContainer();

            _container
                .AddNewExtension<Interception>();           
               

            IConfigurationSource configSource = ConfigurationSourceFactory.Create();
            PolicyInjectionSettings settings = configSource.GetSection(PolicyInjectionSettings.SectionName) as PolicyInjectionSettings;
            if (settings != null)
            {
                settings.ConfigureContainer(_container, configSource);
            }

            _container.Configure<Interception>()
                .SetInterceptorFor<IFoo>(new TransparentProxyInterceptor());

            _container.RegisterType<IFoo, Foo>();
            IFoo foo = _container.Resolve<IFoo>();

            Action<Action> test = new Action<Action>((action) =>
            {
                try
                {
                    action();
                    Console.WriteLine("No exception thrown!");
                }
                catch (Exception e)
                {
                    Console.WriteLine(string.Format("{0}: {1}", e.GetType(), e.Message));
                }
            });

            test(() => foo.EatString(null));
            test(() => foo.EatString("123"));
            test(() => foo.EatString("12345678901234567890"));
            test(() => foo.EatNumber(-1));
            test(() => foo.EatNumber(0));
            test(() => foo.EatNumber(1));
            test(() => foo.EatNumber(15));
            test(() => foo.EatObject(null));
            test(() => foo.EatObject(new Bar() { NumberProperty = 0, StringProperty = null }));
            test(() => foo.EatObject(new Bar() { NumberProperty = 8, StringProperty = "123" }));

            Console.ReadLine();
        }
    }
}

Jan 16, 2009 at 6:50 AM
Hi,

Please see if this helps. Links for Unity InterfaceInterceptor.

http://quickduck.com/blog/2008/11/07/enterprise-library-walkthrough/ - this has a sample app.
http://www.orbifold.net/default/?p=1215
http://www.nventive.net/Blog2/CategoryView,category,net.aspx
http://www.cnblogs.com/MyNameEPC/archive/2008/12/16/1356216.html
http://www.pnpguidance.net/Post/AOPUnityInterfaceInterceptorExampleUnityDependencyInjectionTutorials.aspx


Valiant Dudan
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com
Jan 19, 2009 at 2:17 AM
Hi Valiant,

Thanks for the quick reply. I just looked through each of the examples.
- the quickduck sample: doesn't use Ent Lib 4.1. Instead, the author seems to have re-written call handlers adapting Unity 1.2 to Ent Lib 3.1
- the other samples all demonstrate how to build custom call handlers.

I'm able to get custom call handlers to work just fine - but that's not what I'm trying to do. I'm just trying to reuse the validation / caching call handlers that are bundled with Ent Lib 4.1 using Interface Interception.

Sorry if my first post wasn't clear.

Any help?

Thanks,
Prithvi
Jan 19, 2009 at 8:54 AM

Hi,

I've tried your code and seems like its not behaving properly, I also read the issue entry that you've logged. I'll try to confirm this if this is a bug. But meanwhile maybe you can just use the TransparentProxyInterceptor(), or you could just create an instance of the interfacr using the PIAB.



Valiant Dudan
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com