it:ad:unity:howto:interception

IT:AD:Unity:HowTo:Interception

See: http://msdn.microsoft.com/en-us/library/ff650639.aspx

The basics are expressed here (several concepts at once…you'll have to trawl through the different approachs I was exploring):

using System;
using System.Linq;
using Microsoft.Practices.Unity;


namespace XAct.Spikes.UnityInterception
{
    using System.Reflection;
    using System.Security.Principal;

    using Microsoft.Practices.Unity.InterceptionExtension;

    using XAct.Environment;
    using XAct.Services;

    class Program
    {
        static void Main(string[] args)
        {
            XAct.Services.IoC.UnityBootstrapper.Initialize();

            Microsoft.Practices.Unity.UnityContainer c;

            Microsoft.Practices.Unity.IUnityContainer unityContainer = 
                XAct.Library.Initialization.Status.BindingResults.DependencyInjectionContainer 
                as Microsoft.Practices.Unity.IUnityContainer;

            unityContainer.AddNewExtension<Interception>();

            unityContainer.Configure<Interception>()
                .AddPolicy("TheNameYouLike")
                .AddMatchingRule(new MyRule())
                .AddCallHandler(new BetterAuthenticationHandler());

            unityContainer.Configure<Interception>().SetInterceptorFor<ISomeService>(new InterfaceInterceptor());
            


            var someService = XAct.Shortcuts.ServiceLocate<ISomeService>();

            someService.DoSomething();
            //These two are decorated with a naive implementation of roles
            //Wouldn't do it this way:
            someService.DoSomethingTricky1();
            someService.DoSomethingTricky2();
            //These are decorated with a much better solution:
            someService.DoSomethingTricky3();
            someService.DoSomethingTricky4();

        }
    }

    public interface ISomeService
    {
        void DoSomething();

        void DoSomethingTricky1();

        void DoSomethingTricky2();

        void DoSomethingTricky3();

        
        void DoSomethingTricky4();
    }





    [DefaultBindingImplementation(typeof(ISomeService))]
    public class SomeService:ISomeService
    {

        [MyNonPollutingUpAttribute]
        public virtual void DoSomething()
        {
            Console.WriteLine("DoSomething...");
        }

        [LogExceptions]
        [AuthenticationByAOP(Roles = "BABA")]
        public virtual void DoSomethingTricky1()
        {
            Console.WriteLine("DoSomethingTricky...");
        }

        [AuthenticationByAOP(Roles="ABC")]
        public virtual void DoSomethingTricky2()
        {
            Console.WriteLine("DoSomethingTricky...");
        }


        //OLD WAY OF DOING IT, BUT IT POLUTES THE STACK WITH A UNITY REFRENCE:[BetterAuthenticationByAOP]
        public virtual void DoSomethingTricky3()
        {
            Console.WriteLine("DoSomethingTricky...");
        }
        //OLD WAY OF DOING IT, BUT IT POLUTES THE STACK WITH A UNITY REFRENCE:[BetterAuthenticationByAOP]
        public virtual void DoSomethingTricky4()
        {
            Console.WriteLine("DoSomethingTricky...");
        }
    }



    public interface IAuthorisationByMethodService
    {
        bool AuthenticatePrincipalByMethod(string fullMethodName);
        bool AuthenticatePrincipalByMethod(MethodInfo methodInfo);
    }

    [DefaultBindingImplementation(typeof(IAuthorisationByMethodService))]
    public class AuthorisationByMethodService : IAuthorisationByMethodService
    {
        private readonly IEnvironmentService environmentService;

        public AuthorisationByMethodService(IEnvironmentService environmentService)
        {
            this.environmentService = environmentService;
        }

        public bool AuthenticatePrincipalByMethod(MethodInfo methodInfo)
        {
            string className = methodInfo.ReflectedType.FullName;
            string methodName = methodInfo.Name;

            String fullMethodName = "{0}.{1}".FormatStringInvariantCulture(className, methodName);
            return this.AuthenticatePrincipalByMethod(fullMethodName);
        }
        public bool AuthenticatePrincipalByMethod(string fullMethodName)
        {

            Console.WriteLine("Looking in db or cache or for intersection between MethodName and current Principal Roles");
            Console.WriteLine("...for {0}", fullMethodName);
            return true;
        }
    }


    //define what it is you want to do with your custom interceptor
    public class LogExceptionsHandler : ICallHandler
    {
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {   //Put any logic here you would like to invoke BEFORE the method is invoked.
            Console.WriteLine("Before method Invocation happened");

            //This invokes the next item in the Injection pipeline, or eventually
            //calls your method
            var methodReturn = getNext().Invoke(input, getNext);

            // AFTER the target method execution check to see if it excepted 
            if (methodReturn.Exception != null)
            {
                Console.WriteLine("Add some real logging here");
            }

            //if you would like to re-throw, do it here, otherwise just return 
            //your methodReturn
            else
            {
                Console.WriteLine
                   ("To Rethrow, or not to rethrow, that is the question.");
            }
            return methodReturn;
        }
    }

    public class AuthenticationHandler : ICallHandler
    {
        public AuthenticationHandler()
        {
            
        }
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            
            //This will return the Attributes applied to the INterface (not the Instance)
            AuthenticationByAOPAttribute entryAttrib = input.MethodBase.GetAttribute<AuthenticationByAOPAttribute>(false);
            //To Get to attributes applied to the actual Instance method would require even more expensive Reflection.


            if (entryAttrib != null)
            {
                IPrincipal principal = System.Threading.Thread.CurrentPrincipal;

                string roleNames = entryAttrib.Roles;

                if (!roleNames.IsNullOrEmpty())
                {
                    if (roleNames.Split().First(principal.IsInRole).IsNullOrEmpty())
                    {
                        //Not good...
                        Console.WriteLine("Not in role...");
                    }
                }
            }

            ////service.Trace.AppendLine(entryAttrib.Message);
            //Put any logic here you would like to invoke BEFORE the method is invoked.
            Console.WriteLine("Before method Invocation happened");

            //This invokes the next item in the Injection pipeline, or eventually
            //calls your method
            var methodReturn = getNext().Invoke(input, getNext);

            return methodReturn;
        }
    }


    public class BetterAuthenticationHandler : ICallHandler
    {
        public BetterAuthenticationHandler()
        {

        }
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {

            IAuthorisationByMethodService authorisationByMethodService=
                XAct.Services.ServiceLocatorService.Current.GetInstance<IAuthorisationByMethodService>();


            MethodInfo methodInfo = (MethodInfo) input.MethodBase;
            bool result = authorisationByMethodService.AuthenticatePrincipalByMethod(methodInfo);
            Console.Write("Checking in db...Answer: sure!");

            ////service.Trace.AppendLine(entryAttrib.Message);
            //Put any logic here you would like to invoke BEFORE the method is invoked.
            Console.WriteLine("Before method Invocation happened");

            //This invokes the next item in the Injection pipeline, or eventually
            //calls your method
            var methodReturn = getNext().Invoke(input, getNext);

            return methodReturn;
        }
    }


    //create an attribute so you can apply it to your methods
    public class LogExceptionsAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
        {
            return new LogExceptionsHandler();
        }
    }

    public class AuthenticationByAOPAttribute : HandlerAttribute
    {
        public string Roles { get; set; }

        public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
        {
            return new AuthenticationHandler();
        }
    }
    public class BetterAuthenticationByAOPAttribute : HandlerAttribute
    {

        public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
        {
            return new BetterAuthenticationHandler();
        }
    }


    public class MyRule : IMatchingRule
    {
        public bool Matches(MethodBase member)
        {
            if (member.GetCustomAttribute<MyNonPollutingUpAttribute>() != null)
            {
                return true;
            }

            return member.Name.StartsWith("DoSomethingTricky");
        }
    }
    public class MyNonPollutingUpAttribute :Attribute
    {
        //Prefer to use an app specific (or atleast corp specific) Attribute
        //throughout your Application Facade, rather than use one that 
        //mentions Unity.
    }

}



  • /home/skysigal/public_html/data/pages/it/ad/unity/howto/interception.txt
  • Last modified: 2023/11/04 02:00
  • by 127.0.0.1