Why PIAB interception failure in this simple example?

Topics: Policy Injection Application Block
Feb 27, 2014 at 6:45 AM
/// <summary>
/// StudentBase
/// </summary>
public class Studentbase : MarshalByRefObject
{
    [UserLogCallHandler("test", "test")]
    public virtual bool Update()
    {
        return true;
    }
    public virtual bool Execute()
    {
        return true;
    }
}

/// <summary>
/// Student
/// </summary>
public class Student : Studentbase
{
    public override bool Update()
    {
        return true;
    }

    public override bool Execute()
    {
        return this.Update();
    }
}


 /// <summary>
/// Test,
/// </summary>
[TestFixture]
public class InjectTests
{
    [Test]
    public void StudentInject()
    {
        Type policyInjectionType = typeof(Student);
        object objectStudent = PolicyInjection.Create(policyInjectionType);
        Studentbase studentbase = (Studentbase)objectStudent;

        studentbase.Update(); //intercept the "update" Suceess
        studentbase.Execute();// I want to  Intercept the "update" ,bugt Failed,anything happened, why??????  
    }
}
Feb 27, 2014 at 12:49 PM
Was there an exception thrown? I think you need to initialize PolicyInjection before using the feature.

This sample works for me:
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property)]
    public class UserLogCallHandlerAttribute : HandlerAttribute
    {
        public UserLogCallHandlerAttribute(string value1, string value2)
        {
            Value1 = value1;
            Value2 = value2;
        }

        public string Value1 { get; private set; }

        public string Value2 { get; private set; }

        public override ICallHandler CreateHandler(IUnityContainer ignored)
        {
            return new UserLogCallHandler(Value1, Value2, Order);
        }
    }

    public class UserLogCallHandler : ICallHandler
    {
        public UserLogCallHandler(string value1, string value2, int order)
        {
            Value1 = value1;
            Value2 = value2;
            Order = order;
        }

        public string Value1 { get; private set; }

        public string Value2 { get; private set; }

        public int Order { get; set; }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            Console.WriteLine(Value1);
            var result = getNext().Invoke(input, getNext);
            Console.WriteLine(Value2);

            return result;
        }
    }

    public class Studentbase : MarshalByRefObject
    {
        [UserLogCallHandler("test1", "test2")]
        public virtual bool Update()
        {
            return true;
        }
        public virtual bool Execute()
        {
            return true;
        }
    }

    public class Student : Studentbase
    {
        public override bool Update()
        {
            return true;
        }

        public override bool Execute()
        {
            return this.Update();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();            
            PolicyInjector policyInjector = new PolicyInjector(configurationSource);
            PolicyInjection.SetPolicyInjector(policyInjector); 

            Type policyInjectionType = typeof(Student);
            object objectStudent = PolicyInjection.Create(policyInjectionType);
            Studentbase studentbase = (Studentbase)objectStudent;

            studentbase.Update(); 
            studentbase.Execute();
        }
    }

Hope that helps.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Feb 28, 2014 at 9:15 AM
Thank you for your answer my question, but the problem is not solved.

I refer to your code and run the following code in a new console project without config file. (win7 64 , vs2010, entlib5.0)

I expect it can print the string "test1 test2",because the Statements "return this.Update()" in the method Execute(). I do not konw why It print nothing.

If direct call the update(),It can work well and print the string I expected.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity;

namespace PolicyInjectConsole
{
   
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property)]
    public class UserLogCallHandlerAttribute : HandlerAttribute
    {
        public UserLogCallHandlerAttribute(string value1, string value2)
        {
            Value1 = value1;
            Value2 = value2;
        }

        public string Value1 { get; private set; }

        public string Value2 { get; private set; }

        public override ICallHandler CreateHandler(IUnityContainer ignored)
        {
            return new UserLogCallHandler(Value1, Value2, Order);
        }
    }

    public class UserLogCallHandler : ICallHandler
    {
        public UserLogCallHandler(string value1, string value2, int order)
        {
            Value1 = value1;
            Value2 = value2;
            Order = order;
        }

        public string Value1 { get; private set; }

        public string Value2 { get; private set; }

        public int Order { get; set; }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            Console.WriteLine(Value1);
            var result = getNext().Invoke(input, getNext);
            Console.WriteLine(Value2);

            return result;
        }
    }

    public class Studentbase : MarshalByRefObject
    {
        [UserLogCallHandler("test1", "test2")]
        public virtual bool Update()
        {
            return true;
        }
        public virtual bool Execute()
        {
            return true;
        }
    }

    public class Student : Studentbase
    {
        public override bool Update()
        {
            return true;
        }

        public override bool Execute()
        {
            return this.Update();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Type policyInjectionType = typeof(Student);
            object objectStudent = PolicyInjection.Create(policyInjectionType);
            Studentbase studentbase = (Studentbase)objectStudent;
            studentbase.Execute();
            Console.Read();
        }
    }
}
Feb 28, 2014 at 10:13 AM
I see what you are saying. The reason why the interception isn't working is that the PolicyInjection Application Block uses a TransparentProxyInterceptor. When the object is requested a proxy is returned which performs the interception. However, once the call is in the Student class calls to this will no longer go through the proxy but the underlying object.

The only way to do what you want (that I'm aware of) is to switch to using Unity directly (Unity is providing the infrastructure for the Policy Injection Application Block) and use a VirtualMethodInterceptor. Because a new object type is returned calls to this can be intercepted. However all methods that need to be intercepted must be virtual (which aligns with your sample code).
IUnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();

container.RegisterType<Student>(
    new Interceptor<VirtualMethodInterceptor>(),
    new InterceptionBehavior<PolicyInjectionBehavior>());

object objectStudent = container.Resolve<Student>();
Studentbase studentbase = (Studentbase)objectStudent;

studentbase.Update(); //intercept the "update" Suceess
studentbase.Execute();// I want to  Intercept the "update" ,bugt Failed,anything happened, why??????  

This code will produce the output:
test1
test2
test1
test2

Indicating that 2 interceptions were performed.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Marked as answer by sportsmanair on 3/4/2014 at 5:56 PM