AuthenticationProxy.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
using System.Reflection;
using System.Threading;
namespace ProxyWithAOP
{
public class AuthenticationProxy<T> : RealProxy
{
private readonly T _decorated;
public AuthenticationProxy(T decorated)
: base(typeof(T))
{
_decorated = decorated;
}
private void Log(string msg, object arg = null)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(msg, arg);
Console.ResetColor();
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as MethodInfo;
if (Thread.CurrentPrincipal.IsInRole("ADMIN"))
{
try
{
Log("User authenticated - You can execute '{0}' ", methodCall.MethodName);
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
catch (Exception e)
{
Log(string.Format("User authenticated - Exception {0} executing '{1}'", e), methodCall.MethodName);
return new ReturnMessage(e, methodCall);
}
}
Log("User not authenticated - You can't execute '{0}' ", methodCall.MethodName);
return new ReturnMessage(-1, null, 0, methodCall.LogicalCallContext, methodCall);
}
}
}
DynamicProxy.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ProxyWithAOP
{
class DynamicProxy<T> : RealProxy
{
private readonly T _decorated;
public DynamicProxy(T decorated)
: base(typeof(T))
{
_decorated = decorated;
}
private void Log(string msg, object arg = null)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(msg, arg);
Console.ResetColor();
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as MethodInfo;
Log("In Dynamic Proxy - Before executing '{0}'", methodCall.MethodName);
try
{
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
Log("In Dynamic Proxy - After executing '{0}' ", methodCall.MethodName);
return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
}
catch (Exception e)
{
Log(string.Format("In Dynamic Proxy- Exception {0} executing '{1}'", e), methodCall.MethodName);
return new ReturnMessage(e, methodCall);
}
}
}
}
I have declared two methods as -int GetCustomer(T entity);
and double GetBalance(T entity);
Added methods in pipeline as
var decorated = TraceProxy<ICustomerOperations>.Create(new CustomerOperations());
decorated = AuthenticationProxy<ICustomerOperations>.Create(decorated);
now I am calling my customer methods using decorator as
decorated.GetCustomer(1);
decorated.GetBalance(1);
above methods have distinct return type as int and string.
When user is not authenticated in AuthenticationProxy class, then it returns object as return new ReturnMessage(-1, null, 0, methodCall.LogicalCallContext, methodCall);
(Authentication.cs invoke method)
decorated.GetCustomer(1);
call has been successful as return type match as int
. However decorated.GetBalance(1);
is throwing InvalidCastException
exception as its excepting double
return type value.
So how to resolve this problem? I want to make it generic so that there should not be return type issue.