For a given class I would like to have tracing functionality i.e. I would like to log every method call (method signature and actual parameter values) and every method exit (just the method signature).
How do I accomplish this assuming that:
I don't want to use any 3rd party
AOP libraries for C#,
I don't want to add duplicate code to all the methods that I want to trace,
I don't want to change the public API of the class - users of the class should be able to call all the methods in exactly the same way.
To make the question more concrete let's assume there are 3 classes:
public class Caller
{
public static void Call()
{
Traced traced = new Traced();
traced.Method1();
traced.Method2();
}
}
public class Traced
{
public void Method1(String name, Int32 value) { }
public void Method2(Object object) { }
}
public class Logger
{
public static void LogStart(MethodInfo method, Object[] parameterValues);
public static void LogEnd(MethodInfo method);
}
How do I invoke Logger.LogStart and Logger.LogEnd for every call to Method1 and Method2 without modifying the Caller.Call method and without adding the calls explicitly to Traced.Method1 and Traced.Method2?
Edit: What would be the solution if I'm allowed to slightly change the Call method?
C# is not an AOP oriented language. It has some AOP features and you can emulate some others but making AOP with C# is painful.
I looked up for ways to do exactly what you wanted to do and I found no easy way to do it.
As I understand it, this is what you want to do:
[Log()]
public void Method1(String name, Int32 value);
and in order to do that you have two main options
Inherit your class from MarshalByRefObject or ContextBoundObject and define an attribute which inherits from IMessageSink. This article has a good example. You have to consider nontheless that using a MarshalByRefObject the performance will go down like hell, and I mean it, I'm talking about a 10x performance lost so think carefully before trying that.
The other option is to inject code directly. In runtime, meaning you'll have to use reflection to "read" every class, get its attributes and inject the appropiate call (and for that matter I think you couldn't use the Reflection.Emit method as I think Reflection.Emit wouldn't allow you to insert new code inside an already existing method). At design time this will mean creating an extension to the CLR compiler which I have honestly no idea on how it's done.
The final option is using an IoC framework. Maybe it's not the perfect solution as most IoC frameworks works by defining entry points which allow methods to be hooked but, depending on what you want to achive, that might be a fair aproximation.
The simplest way to achieve that is probably to use PostSharp. It injects code inside your methods based on the attributes that you apply to it. It allows you to do exactly what you want.
Another option is to use the profiling API to inject code inside the method, but that is really hardcore.
You could achieve it with Interception feature of a DI container such as Castle Windsor. Indeed, it is possible to configure the container in such way that every classes that have a method decorated by a specific attribute would be intercepted.
Regarding point #3, OP asked for a solution without AOP framework. I assumed in the following answer that what should be avoided were Aspect, JointPoint, PointCut, etc. According to Interception documentation from CastleWindsor, none of those are required to accomplish what is asked.
Configure generic registration of an Interceptor, based on the presence of an attribute:
public class RequireInterception : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (HasAMethodDecoratedByLoggingAttribute(model.Implementation))
{
model.Interceptors.Add(new InterceptorReference(typeof(ConsoleLoggingInterceptor)));
model.Interceptors.Add(new InterceptorReference(typeof(NLogInterceptor)));
}
}
private bool HasAMethodDecoratedByLoggingAttribute(Type implementation)
{
foreach (var memberInfo in implementation.GetMembers())
{
var attribute = memberInfo.GetCustomAttributes(typeof(LogAttribute)).FirstOrDefault() as LogAttribute;
if (attribute != null)
{
return true;
}
}
return false;
}
}
Add the created IContributeComponentModelConstruction to container
container.Kernel.ComponentModelBuilder.AddContributor(new RequireInterception());
And you can do whatever you want in the interceptor itself
public class ConsoleLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Writeline("Log before executing");
invocation.Proceed();
Console.Writeline("Log after executing");
}
}
Add the logging attribute to your method to log
public class Traced
{
[Log]
public void Method1(String name, Int32 value) { }
[Log]
public void Method2(Object object) { }
}
Note that some handling of the attribute will be required if only some method of a class needs to be intercepted. By default, all public methods will be intercepted.
If you write a class - call it Tracing - that implements the IDisposable interface, you could wrap all method bodies in a
Using( Tracing tracing = new Tracing() ){ ... method body ...}
In the Tracing class you could the handle the logic of the traces in the constructor/Dispose method, respectively, in the Tracing class to keep track of the entering and exiting of the methods. Such that:
public class Traced
{
public void Method1(String name, Int32 value) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
public void Method2(Object object) {
using(Tracing tracer = new Tracing())
{
[... method body ...]
}
}
}
If you want to trace after your methods without limitation (no code adaptation, no AOP Framework, no duplicate code), let me tell you, you need some magic...
Seriously, I resolved it to implement an AOP Framework working at runtime.
You can find here : NConcern .NET AOP Framework
I decided to create this AOP Framework to give a respond to this kind of needs. it is a simple library very lightweight. You can see an example of logger in home page.
If you don't want to use a 3rd party assembly, you can browse the code source (open source) and copy both files Aspect.Directory.cs and Aspect.Directory.Entry.cs to adapted as your wishes. Theses classes allow to replace your methods at runtime. I would just ask you to respect the license.
I hope you will find what you need or to convince you to finally use an AOP Framework.
Take a look at this - Pretty heavy stuff..
http://msdn.microsoft.com/en-us/magazine/cc164165.aspx
Essential .net - don box had a chapter on what you need called Interception.
I scraped some of it here (Sorry about the font colors - I had a dark theme back then...)
http://madcoderspeak.blogspot.com/2005/09/essential-interception-using-contexts.html
I have found a different way which may be easier...
Declare a Method InvokeMethod
[WebMethod]
public object InvokeMethod(string methodName, Dictionary<string, object> methodArguments)
{
try
{
string lowerMethodName = '_' + methodName.ToLowerInvariant();
List<object> tempParams = new List<object>();
foreach (MethodInfo methodInfo in serviceMethods.Where(methodInfo => methodInfo.Name.ToLowerInvariant() == lowerMethodName))
{
ParameterInfo[] parameters = methodInfo.GetParameters();
if (parameters.Length != methodArguments.Count()) continue;
else foreach (ParameterInfo parameter in parameters)
{
object argument = null;
if (methodArguments.TryGetValue(parameter.Name, out argument))
{
if (parameter.ParameterType.IsValueType)
{
System.ComponentModel.TypeConverter tc = System.ComponentModel.TypeDescriptor.GetConverter(parameter.ParameterType);
argument = tc.ConvertFrom(argument);
}
tempParams.Insert(parameter.Position, argument);
}
else goto ContinueLoop;
}
foreach (object attribute in methodInfo.GetCustomAttributes(true))
{
if (attribute is YourAttributeClass)
{
RequiresPermissionAttribute attrib = attribute as YourAttributeClass;
YourAttributeClass.YourMethod();//Mine throws an ex
}
}
return methodInfo.Invoke(this, tempParams.ToArray());
ContinueLoop:
continue;
}
return null;
}
catch
{
throw;
}
}
I then define my methods like so
[WebMethod]
public void BroadcastMessage(string Message)
{
//MessageBus.GetInstance().SendAll("<span class='system'>Web Service Broadcast: <b>" + Message + "</b></span>");
//return;
InvokeMethod("BroadcastMessage", new Dictionary<string, object>() { {"Message", Message} });
}
[RequiresPermission("editUser")]
void _BroadcastMessage(string Message)
{
MessageBus.GetInstance().SendAll("<span class='system'>Web Service Broadcast: <b>" + Message + "</b></span>");
return;
}
Now I can have the check at run time without the dependency injection...
No gotchas in site :)
Hopefully you will agree that this is less weight then a AOP Framework or deriving from MarshalByRefObject or using remoting or proxy classes.
First you have to modify your class to implement an interface (rather than implementing the MarshalByRefObject).
interface ITraced {
void Method1();
void Method2()
}
class Traced: ITraced { .... }
Next you need a generic wrapper object based on RealProxy to decorate any interface to allow intercepting any call to the decorated object.
class MethodLogInterceptor: RealProxy
{
public MethodLogInterceptor(Type interfaceType, object decorated)
: base(interfaceType)
{
_decorated = decorated;
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase;
Console.WriteLine("Precall " + methodInfo.Name);
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
Console.WriteLine("Postcall " + methodInfo.Name);
return new ReturnMessage(result, null, 0,
methodCall.LogicalCallContext, methodCall);
}
}
Now we are ready to intercept calls to Method1 and Method2 of ITraced
public class Caller
{
public static void Call()
{
ITraced traced = (ITraced)new MethodLogInterceptor(typeof(ITraced), new Traced()).GetTransparentProxy();
traced.Method1();
traced.Method2();
}
}
You can use open source framework CInject on CodePlex. You can write minimal code to create an Injector and get it to intercept any code quickly with CInject. Plus, since this is Open Source you can extend this as well.
Or you can follow the steps mentioned on this article on Intercepting Method Calls using IL and create your own interceptor using Reflection.Emit classes in C#.
I don't know a solution but my approach would be as follows.
Decorate the class (or its methods) with a custom attribute. Somewhere else in the program, let an initialization function reflect all types, read the methods decorated with the attributes and inject some IL code into the method. It might actually be more practical to replace the method by a stub that calls LogStart, the actual method and then LogEnd. Additionally, I don't know if you can change methods using reflection so it might be more practical to replace the whole type.
You could potentially use the GOF Decorator Pattern, and 'decorate' all classes that need tracing.
It's probably only really practical with an IOC container (but as pointer out earlier you may want to consider method interception if you're going to go down the IOC path).
you need to bug Ayende for an answer on how he did it:
http://ayende.com/Blog/archive/2009/11/19/can-you-hack-this-out.aspx
AOP is a must for clean code implementing, however if you want to surround a block in C#, generic methods have relatively easier usage. (with intelli sense and strongly typed code) Certainly, it can NOT be an alternative for AOP.
Although PostSHarp have little buggy issues (i do not feel confident for using at production), it is a good stuff.
Generic wrapper class,
public class Wrapper
{
public static Exception TryCatch(Action actionToWrap, Action<Exception> exceptionHandler = null)
{
Exception retval = null;
try
{
actionToWrap();
}
catch (Exception exception)
{
retval = exception;
if (exceptionHandler != null)
{
exceptionHandler(retval);
}
}
return retval;
}
public static Exception LogOnError(Action actionToWrap, string errorMessage = "", Action<Exception> afterExceptionHandled = null)
{
return Wrapper.TryCatch(actionToWrap, (e) =>
{
if (afterExceptionHandled != null)
{
afterExceptionHandled(e);
}
});
}
}
usage could be like this (with intelli sense of course)
var exception = Wrapper.LogOnError(() =>
{
MessageBox.Show("test");
throw new Exception("test");
}, "Hata");
Maybe it's to late for this answer but here it goes.
What you are looking to achieve is built in MediatR library.
This is my RequestLoggerBehaviour which intercepts all calls to my business layer.
namespace SmartWay.Application.Behaviours
{
public class RequestLoggerBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly ILogger _logger;
private readonly IAppSession _appSession;
private readonly ICreateLogGrain _createLogGrain;
public RequestLoggerBehaviour(ILogger<TRequest> logger, IAppSession appSession, IClusterClient clusterClient)
{
_logger = logger;
_appSession = appSession;
_createLogGrain = clusterClient.GetGrain<ICreateLogGrain>(Guid.NewGuid());
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var name = typeof(TRequest).Name;
_logger.LogInformation($"SmartWay request started: ClientId: {_appSession.ClientId} UserId: {_appSession.UserId} Operation: {name} Request: {request}");
var response = await next();
_logger.LogInformation($"SmartWay request ended: ClientId: {_appSession.ClientId} UserId: {_appSession.UserId} Operation: {name} Request: {request}");
return response;
}
}
}
You can also create performance behaviours to trace methods that take too long to execute for example.
Having clean architecture (MediatR) on your business layer will allow you to keep your code clean while you enforce SOLID principles.
You can see how it works here:
https://youtu.be/5OtUm1BLmG0?t=1
Write your own AOP library.
Use reflection to generate a logging proxy over your instances (not sure if you can do it without changing some part of your existing code).
Rewrite the assembly and inject your logging code (basically the same as 1).
Host the CLR and add logging at this level (i think this is the hardest solution to implement, not sure if you have the required hooks in the CLR though).
The best you can do before C# 6 with 'nameof' released is to use slow StackTrace and linq Expressions.
E.g. for such method
public void MyMethod(int age, string name)
{
log.DebugTrace(() => age, () => name);
//do your stuff
}
Such line may be produces in your log file
Method 'MyMethod' parameters age: 20 name: Mike
Here is the implementation:
//TODO: replace with 'nameof' in C# 6
public static void DebugTrace(this ILog log, params Expression<Func<object>>[] args)
{
#if DEBUG
var method = (new StackTrace()).GetFrame(1).GetMethod();
var parameters = new List<string>();
foreach(var arg in args)
{
MemberExpression memberExpression = null;
if (arg.Body is MemberExpression)
memberExpression = (MemberExpression)arg.Body;
if (arg.Body is UnaryExpression && ((UnaryExpression)arg.Body).Operand is MemberExpression)
memberExpression = (MemberExpression)((UnaryExpression)arg.Body).Operand;
parameters.Add(memberExpression == null ? "NA" : memberExpression.Member.Name + ": " + arg.Compile().DynamicInvoke().ToString());
}
log.Debug(string.Format("Method '{0}' parameters {1}", method.Name, string.Join(" ", parameters)));
#endif
}
Related
I'm on .NET 4.8, under Windows Forms. I have a specific amount of declared methods inside a project, in various classes. And I would like that every method in these classes to call another specific method at the very start of each method execution. What I mean it's like If I manually add the required code at line number one inside each method body to call this other specific method.
Why I would like to do this?: I wrote a specific method that prints debug information on which I'm interested to know. This method includes info about the caller member, but it is not in any way limited to that kind of info.
Then, while I'm developing any application in Debug mode I would like to call this method automatically on every other method call in my project (inside property getter/setter too, if possible), and I'm just very curious to know if exists an alternative to the nightmare of writing/copying a thousand times the required instruction to call this specific method inside each method body in the project.
Exists a way to achieve this at runtime?. Maybe... writing an helper method that would be called once to retrieve all declared methods through Reflection and do code injection points in their method bodies?. Not sure how to do so, and not sure if that is viable anyways; maybe with Reflection.Emit as suggested in this answer?
And could this be achieved without depending on third party dependencies like Postsharp as suggested in this question?. Really using Postsharp is not a viable solution for me because I suppose the solution will consist to decorate with custom attributes every declared method in the project.
I also found this other suggestion but it's basically what I intend to avoid: manually add code changes to every method call in the project (in this case to replace the invocation code).
Some suggestions that I found like that last are not applicable to my scenario because I need to call this specific method INSIDE / FROM the method body of other methods in order to be able retrieve debug info of the current caller member including its parameters and values.
As an option, RealProxy may help. There's a nice article by Bruno Sonnino on this topic: Aspect-Oriented Programming : Aspect-Oriented Programming with the RealProxy Class.
Also you may be able to use AOP features of Unity (the DI framework) for this purpose. There's a nice article on this topic by Dino Esposito: Interceptors in Unity.
Using a weaving tool like Fody is also another option.
Creating proxy classes using Reflection.Emit could be another option.
Example - AOP using RealProxy
A LogAttribute which Has MethodExecuting and MethodExecuted and runs before and after methods
Using RealProxy, you can create a proxy for your class, so that when you call a method, the Invoke method of the proxy will run and you can run any logic there, for example you can run something before or after the actual method call.
In this example, I show how you can create a MethodFilterAttribute having two methods OnMethodExecuting and OnMethodExecuted, and then if you decorate your method with an attribute derived from this attribute, those methods will run before and after executing of the original method.
Looking into the code, you see you don't necessarily need the attributes, and attributes are just there as an extensibility point.
The usage of the code in this example is something like this:
var calc = CalculatorFactory.GetInstance();
var a = calc.Add(1, 2);
var b = calc.Subtract(1, 2);
Which produce the output:
Add executing.
Add executed.
Subtract executing.
Subtract executed.
Using statements
This is an attribute that could be used for methods. It has OnMethodExecuting and OnMethodExecuted methods, and when you get a proxy of your class, and run the methods, these two filter methods will be executed before and after the method which is decorated by this attribute:
using System;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Linq;
[AttributeUsage(AttributeTargets.Method)]
public class MethodFilterAttribute : Attribute
{
public int Order { get; set; }
public virtual void OnMethodExecuting(
MethodInfo methodInfo, object[] args) { }
public virtual void OnMethodExecuted(
MethodInfo methodInfo, object[] args, object result) { }
}
LogAttribute
An implementation of MethodFilterAttribute which performs log before and after method execution:
public class LogAttribute : MethodFilterAttribute
{
override public void OnMethodExecuting(
MethodInfo methodInfo, object[] args)
{
Console.WriteLine($"{methodInfo.Name} executing.");
}
override public void OnMethodExecuted(
MethodInfo methodInfo, object[] args, object result)
{
Console.WriteLine($"{methodInfo.Name} executed.");
}
}
The DynamicProxy class
Creates a proxy of your object, and if you run methods of the object, if the methdod is decorated with a method filter attribute, then OnActionExecuting and OnActionExecuted will run.
Looking into the code, you see you don't necessarily need the attributes, and attributes are just there as an extensibility point.
public class DynamicProxy<T> : RealProxy
{
private readonly T original;
public DynamicProxy(T original)
: base(typeof(T))
{
this.original = original;
}
public override IMessage Invoke(IMessage msg)
{
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as MethodInfo;
try
{
var filters = methodInfo.GetCustomAttributes<MethodFilterAttribute>();
if (filters.Any())
{
filters.OrderBy(x => x.Order).ToList()
.ForEach(f => f.OnMethodExecuting(methodInfo, methodCall.InArgs));
}
var result = methodInfo.Invoke(original, methodCall.InArgs);
if (filters.Any())
{
filters.OrderBy(x => x.Order).ToList()
.ForEach(f => f.OnMethodExecuted(methodInfo, methodCall.InArgs, result));
}
return new ReturnMessage(result, null, 0,
methodCall.LogicalCallContext, methodCall);
}
catch (Exception e)
{
return new ReturnMessage(e, methodCall);
}
}
}
ICalculator interface and Calculator class
Methods of Calculator are decorated with Log attribute, which means before and after execution of those methods, log will run.
Please note: In the implementation of the proxy we are looking for the attributes, using the interface. Also having the interface is necessary.
public interface ICalculator
{
[Log]
int Add(int x, int y);
[Log]
int Subtract(int x, int y);
}
public class Calculator : ICalculator
{
public int Add(int x, int y)
{
return x + y;
}
public int Subtract(int x, int y)
{
return x - y;
}
}
CalculatorFactory
The factory which returns a proxy instance of ICalculator:
public class CalculatorFactory
{
public static ICalculator GetInstance()
{
var original = new Calculator();
return new DynamicProxy<ICalculator>(original)
.GetTransparentProxy() as ICalculator;
}
}
Usage
Get an proxied instance of the interface using the factory and run methods:
var calc = CalculatorFactory.GetInstance();
var a = calc.Add(1, 2);
var b = calc.Subtract(1, 2);
Which produce the output:
Add executing.
Add executed.
Subtract executing.
Subtract executed.
So I have a few instances where I'd like to be able to do this but essentially I'd like to be able to wrap all calls to a Superclass in a derived type. Right now I'm trying to wrap all calls to base method in an Impersonator but I can see other uses for this as well.
An example being
public void CopyFile(string filePath, string destPath)
{
using(var I = new Impersonator("user", ".", "password"))
{
base.CopyFile(string filePath, string destPath);
}
}
Another convenient use might be
public void CopyFile(string filePath, string destPath)
{
try
{
base.CopyFile(string filePath, string destPath);
} catch(Exception e)
{
Log(e.Message);
}
}
Now I'd like to wrap all base calls similarly. Is there a convenient way to do this or do I have to wrap all of these manually?
I'm looking for something like a "foreach baseMethod in Superclass Do This"
Perhaps finding some way to capture incoming calls to the class and wrapping them as an action?
public void ActionWrapper(Action action)
{
try
{
action.Invoke();
} catch(Exception e)
{
Log(e.Message);
}
}
But how would I catch calls to the class in that way?
Honestly this is just to make the class more maintainable and reduce code bloat. I'm open to these or any other approaches.
First, I want to applaud your instinct to deconstruct code this way. Separating concerns like error handling/logging and security/identity from your business logic can do wonders for maintainability.
What you're describing is known as either decoration or interception. Mark Seemann has a good blog post comparing the two approaches in the context of logging.
Without using external tools (like a DI or AOP framework), I think the ActionWrapper method you proposed is a good start. I modified it to show impersonation rather than logging, since I think impersonation is a more interesting use case:
public void ActionWrapper(Action action)
{
using(var I = new Impersonator("user", ".", "password"))
{
action.Invoke();
}
}
So the question is: How to apply this method efficiently?
Let's assume your existing class is:
public class FileCopier
{
public void CopyFile(string filePath, string destPath)
{
// Do stuff
}
}
You could, as you suggested, create a derived class to add impersonation:
public class FileCopierWithImpersonation : FileCopier
{
public void CopyFile(string filePath, string destPath)
=> WithImpersonation(base.CopyFile(filePath, destPath));
public void WithImpersonation(Action action)
{
using(var I = new Impersonator("user", ".", "password"))
{
action.Invoke();
}
}
}
Here, FileCopierWithImpersonation serves as a decorator over FileCopier, implemented via inheritance. The WithImpersonation method serves as an interceptor that can apply an impersonation scope over any method.
That should work well enough, but it forces some compromises in implementation. The base class's methods will all need to be marked as virtual. The child class's constructor might need to pass arguments to the base class. It will be impossible to unit test the child class's logic independently of the base class's logic.
So, you might want to extract an interface (IFileCopier) and apply the decorator using composition rather than inheritance:
public class FileCopierWithImpersonation : IFileCopier
{
private readonly IFileCopier _decoratee;
public FileCopierWithImpersonation(IFileCopier decoratee)
{
// If you don't want to inject the dependency, you could also instantiate
// it here: _decoratee = new FileCopier();
_decoratee = decoratee;
}
public void CopyFile(string filePath, string destPath)
=> WithImpersonation(_decoratee.CopyFile(filePath, destPath));
public void WithImpersonation(Action action)
{
using(var I = new Impersonator("user", ".", "password"))
{
action.Invoke();
}
}
}
If you're using Visual Studio 2019, there's a refactoring option to "Implement Interface through..." that will automatically implement an interface by calling methods of a dependency of the same type. After that, a simple find/replace should be all that's needed to add the interceptor.
You could also look into code generation tools, like T4 Templates to auto-generate the decorators. Beware, though, that T4 is not supported in .NET Core. It looks to be a legacy technology at this point.
From a good design perspective, I would advise not to do this for 2 reasons:
If catching exception is the sole purpose, then don't do it. Catching and swallowing system exceptions is a bad practice
If you want to do some pre-setup or post-processing on every method of base then may be you should choose composition rather than inheritance here.
However, if you have made up your mind then using an array of delegates can solve your problem.
class Derived : Base
{
private Action[] AllActions;
public Derived()
{
AllActions = new Action[]
{
base.DoSomething1,
base.DoSomething2,
base.DoSomethingMore
};
}
public ActionWrapper(int index)
{
try
{
AllActions[index].Invoke();
} catch(Exception e)
{
Log(e.Message);
}
}
}
For simplicity I have used an array. Use a dictionary to keep a key for each base class method.
I see AOP has been suggested but not expanded upon, so I will attempt to cover it then.
I am assuming you are open to making your base class methods virtual. In this case using a Castle DynamicProxy might give you the flexibility you are after. It will allow you to not only inject code before and after parent method execution, but also change input/output parameters depending on your business requirements.
Here's an artist's impression on what your class might look like should you opt for it:
public class FileCopier
{
public virtual void CopyFile(string filePath, string destPath)
{
// do things here
}
}
public class ImpersonationInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
using (var I = new Impersonator("user", ".", "password"))
{
invocation.Proceed();
}
}
}
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
}
catch (Exception e)
{
Log(e.Message);
}
}
}
public class CustomProxyGenerationHook : IProxyGenerationHook
{
public void MethodsInspected() {}
public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo) {}
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
// decide whether you need to intercept your method here
return true;
}
}
void Main()
{
var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions(new CustomProxyGenerationHook());
var fileCopierProxy = generator.CreateClassProxy(typeof(FileCopier),
options
new IInterceptor[] { // specify list of interceptors
new ImpersonationInterceptor(),
new LoggingInterceptor()
}
) as FileCopier;
fileCopierProxy.CopyFile("src", "dest");
}
Even if you've got a ton of classes and modifying them all by hand is not feasible, you can still work around it by opting for yet another technique called assembly weaving. Project Fody is a good starting point, and this particular problem is best solved with Virtuosity plugin - it basically rewrites your assembly on build to mark all methods virtual so you don't have to do it yourself.
public static T DecoratorActions<T>(string desc, Func<T> func)
{
return Log(desc, () => ImpersonateAndAct(func));
}
public static void DecoratorActions(string desc, Action action)
{
Log(desc, () => ImpersonateAndAct(action));
}
public string Read(string filepath)
{
return DecoratorActions($"Reading file at '{filepath}'",
() => fileService.Read(filepath));
}
Based on these very helpful answers I've been able to determine that, while I may not be able to automatically wrap all methods of a class. I can at least reduce boilplate code and separate concerns by using the Decorator Pattern instead of the standard inheritance.
As such I have a Log method which calls "Entering {methodName}" and "Exiting {methodName}" as well as try/catching for exceptions which it also logs before throwing.
Additionally an inline way of impersonating for a specific action in the ImpersonateAndAct method.
Both of these return type of T so they wrap calls to my decorated fileService without interfering with the products of those methods.
I marked #Xander as the correct answer as he was the chief inspiration for this approach but I wanted to leave an answer to share what I came up with.
Is there a way to call a method to be executed before another method, like a trigger?
Something like an attribute that indicates the method to be executed, like this:
[OnBefore(MethodToBeExecutedBefore)]
public void MethodExecutedNormally()
{
//method code
}
I have a situation that I need to call a check method very often, and most of the time, they are before methods that take too long to execute.
There is no built in way to achieve this result, if you are using a dependency injection mechanism you can use the interception facilities if the DI framework supports this. (Ex: Unity, NInject)
If you want to go low level you can also use Reflection.Emit to create a derived class at runtime, that overrides methods with a particular attribute that invokes any extra functionality you want, but that is more difficult.
What you are talking about is called AOP or Aspect Oriented Programming.
There are no built-in options in C#. While Attributes exists, there is no mechanism to take any actions with them. You always need a piece of code that reads those attributes and then does something. Attributes themselves are only metadata and markers.
As far as external tools go, Postsharp is the de-facto standard AOP postcompiler for .NET, but it's not free (at least not for real use, there is a free version you may want to try, maybe it's enough for your use-case).
I think you should consider an event driven approach.
You could create an interface and some base classes to handle the event, then have your long running classes inherit from it. Subscribe to the event and handle accordingly:
public delegate void BeforeMethodExecutionHandler<TArgs>(ILongRunningWithEvents<TArgs> sender, TArgs args, string caller);
public interface ILongRunningWithEvents<TArgs>
{
event BeforeMethodExecutionHandler<TArgs> OnBeforeMethodExecution;
}
public class LongRunningClass<TArgs> : ILongRunningWithEvents<TArgs>
{
private BeforeMethodExecutionHandler<TArgs> _onBeforeMethodExecution;
public event BeforeMethodExecutionHandler<TArgs> OnBeforeMethodExecution
{
add { _onBeforeMethodExecution += value; }
remove { _onBeforeMethodExecution -= value; }
}
protected void RaiseOnBeforeMethodExecution(TArgs e, [CallerMemberName] string caller = null)
{
_onBeforeMethodExecution?.Invoke(this, e, caller);
}
}
public class ConcreteRunningClass : LongRunningClass<SampleArgs>
{
public void SomeLongRunningMethod()
{
RaiseOnBeforeMethodExecution(new SampleArgs("Starting!"));
//Code for the method here
}
}
public class SampleArgs
{
public SampleArgs(string message)
{
Message = message;
}
public string Message { get; private set; }
}
Sample usage:
public static void TestLongRunning()
{
ConcreteRunningClass concrete = new ConcreteRunningClass();
concrete.OnBeforeMethodExecution += Concrete_OnBeforeMethodExecution;
concrete.SomeLongRunningMethod();
}
private static void Concrete_OnBeforeMethodExecution(ILongRunningWithEvents<SampleArgs> sender, SampleArgs args, string caller)
{
Console.WriteLine("{0}: {1}", caller ?? "unknown", args.Message);
}
The message SomeLongRunningMethod: Starting! will be output before the long-running method executes.
You could add the caller name to the args. I whipped this out real quick to illustrate.
UPDATE: I see you added tags for ASP.NET MVC. The concept still applies to controllers as controllers are just classes.
I have a custom attribute now I didn't know that how to restrict the access to the method on which I have applied my attribute.
For example: I have custom attribute say "CustomRole" now if value of CustomRole is "Admin" then and only then it should access method.
CustomRole["Admin"]
public void Method()
{
// code
}
How to perform verify the value?
You need some kind of aspect oriented programming approach here. Attribute itself can't 'access' the method as it is not evaluated by the runtime, but you might use some framework which will intercept the call, check the attribute and context and properly handle the case.
So in short, you will:
decorate a method with an attribute
provide an interceptor to handle the call
instantiate the class via some tools which provides AOP functionality
execute the call. The call will be intercepted and handled according to your implementation
Specifying the requirements
As you already noted, this can be easily specified with attributes:
[RequiredPermission(Permissions.CanCreateOrder)]
public virtual Guid CreateOrder(string orderCode) {...}
Intercepting the call
Now you need to pick a tool which will instantiate your object and intercept calls to it. This can be done with IoC containers which support AOP, or you can wrap it manually (e.g. use an AOP tool to create a proxy to the object and use the proxy).
You need to write an interceptor, or a wrapper method which has a chance to evaluate the call context before forwarding the execution to your method or rejecting the call.
You can find a discussion and code samples here. Take a look at OrderManagementService class which declares requirements via attribute.
Poor man's AOP
You can do all of this without resorting to proper AOP tools, but in a less generic way (which may be perfectly fine for simpler projects), using some form of Decorator pattern - please note, this is written from head, not in IDE:
interface IService
{
void Method();
}
class ServiceImpl : IService // one of many implementations
{
[CustomRole("Admin")]
public void Method() { ... }
}
class ServiceChecker : IService // one of many implementations
{
IService m_svc;
public ServiceChecker(IService wrapped) { m_svc = wrapped; }
public void Method()
{
var mi = m_svc.GetType().GetMethod("Method");
if(mi.IsDefined(typeof(CustomRoleAttribute), true)
{
CustomRoleAttribute attr = (CustomRoleAttribute)mi.GetCustomAttributes(typeof(CustomRoleAttribute), true)[0];
if(!attr.Role.Equals( GetCurrentUserRole() ) // depends on where you get user data from
{
throw new SecurityException("Access denied");
}
}
m_svc.Method();
}
}
// the client code
IService svc = new ServiceChecker(new ServiceImpl());
svc.Method();
Your code looks a little bit wrong.
Here is my class with the method with a CustomRoleAttribute
public class MyClass
{
[CustomRole("Admin")]
public void MyMethod()
{
}
}
You attribute should define the AttributeUsage to ensure other developers not uses your attribute on a property or constructor:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false,Inherited = true)]
public class CustomRoleAttribute : Attribute
{
public string Role { get; private set; }
public CustomRoleAttribute(string role)
{
Role = role;
}
}
And now put both together:
MyClass myClass = new MyClass();
MethodInfo[] methods = myClass.GetType().GetMethods(); // Access all the public methods.
foreach (var methodInfo in methods) // iterate trough all methods.
{
// Get all custom attributes from the method.
object[] attributes = methodInfo.GetCustomAttributes(typeof (CustomRoleAttribute), true);
if (attributes.Length > 0)
{
CustomRoleAttribute attribute = (CustomRoleAttribute)attributes[0];
if (attribute.Role == "Admin")
{
// the role is admin
}
}
}
You see now, how to use attributes. Bu you must first check the attribute and than access the method.
Not sure if i'm naming it correctly (i.e. nested interface implementations). However I do not understand the benefit of using dynamic proxy over nested interface implementations. How is dynamic proxy better than doing what the sample code below does? Is the following sample code in some way more limiting that the interceptor pattern used in DynamicProxy?
UPDATE
I understand what cross-cutting concerns are and how DynamicProxy makes maintaining these situations easier. Things like logging exceptions are independent of what the actual code being executed is doing. This example is not universal in nature like the logging example. Eat is how a cookie you eat a cookie. It should not be concerned with when you should eat it. A less contrived example would be a query service that determines if it should call an implementation that uses a local storage, or call an implementation that makes a network call for specific queries. Based on if it has received a message on the bus for an item update contained in the local storage. How would using a DynamicProxy interceptor in cases like these be advantageous for code maintenance?
using System;
using Castle.Windsor;
using Castle.MicroKernel.Registration;
namespace ConsoleApplication19 {
public enum SmellsLike { Poo, YummyCookie }
public class Cookie {
public SmellsLike SmellsLike { get; set; }
public int Size { get; set; }
}
public interface IHaveCookies {
Cookie Eat(Cookie c);
void OtherOperation(Cookie c);
}
// this would be the interceptor if implemented using DynamicProxy
// e.g. interceptor or decorator pattern
public class SmellService : IHaveCookies {
IHaveCookies _;
public SmellService(IHaveCookies implementation) {
_ = implementation;
}
public Cookie Eat(Cookie c) {
Console.WriteLine("Smelling cookie");
// intercept call to Eat and don't call it if it smells like poo
return c.SmellsLike == SmellsLike.Poo
? c
: _.Eat(c);
}
// shows that i'm not intercepting this call
void OtherOperation(Cookie c) {
// do nothing
_.OtherOperation(c);
}
}
//This is the actual service implementation
public class EatService : IHaveCookies {
public Cookie Eat(Cookie c) {
Console.WriteLine("Eating cookie");
var whatsLeft = NomNomNom(c);
return whatsLeft;
}
Cookie NomNomNom(Cookie c) {
c.Size--;
return c;
}
public void OtherOperation(Cookie c) {
// do something else
}
}
// shor program that uses windsor to wire up the interfaces
class Program {
static void Main(string[] args) {
var container = new WindsorContainer();
container.Register(
// interface implementation that is actually given when
// container.Resolve is called
Component.For<IHaveCookies>().ImplementedBy<SmellService>().Named("Smell"),
// wiring up actual service implementation
Component.For<IHaveCookies>().ImplementedBy<EatService>().Named("Eat"),
// this injects the interceptor into the actual service implementation
Component.For<SmellService>().ServiceOverrides(ServiceOverride.ForKey("implementation").Eq("Eat")));
// example usage
var yummy = new Cookie { Size = 2, SmellsLike = SmellsLike.YummyCookie };
var poo = new Cookie { Size = 2, SmellsLike = SmellsLike.Poo };
var svc = container.Resolve<IHaveCookies>();
Console.WriteLine("eating yummy");
// EatService.Eat gets called, as expected
svc.Eat(yummy);
Console.WriteLine("eating poo");
// EatService.Eat does not get called, as expected
svc.Eat(poo);
Console.WriteLine("DONE");
Console.ReadLine();
}
}
}
Dynamic proxy - interceptor - let's you intercept calls to any interface. So let's say you want intercept any cally in any implementation of any interface. How many decorators you would have to implement? And all of them would contain same code but receive different interface in constructor. And they would have to implement all methods of decorated interface. So much repetitive code. Boring and not DRY.
With Castle you can Implement IInterceptor once and use it to do what's described above.
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// log method call and parameters
try
{
invocation.Proceed();
}
catch (Exception e)
{
// log exception
throw; // or sth else
}
}
}
Answer to your UPDATE:
It wouldn't be advantageous. And probably wrong. Or maybe I don't understand what you mean. Maybe this?
public class ServiceSelectingWhatCallToMake : IHaveCookies
{
public ServiceSelectingWhatCallToMake(IHaveCookies localCalls, IHaveCookies networkCalls)
{
// save in member variables
}
public SomeMethod()
{
if (somethingDescribingIShouldMakeLocalCall)
this.localCalls.SomeMethod();
else
this.networkCalls.SomeMethod();
}
}
Then it should really be this
public class ServiceThatDoesntKnowWhatCallItMakes
{
public ServiceSelectingWhatCallToMake(IHaveCookiesFactory factory)
{
// save in member variables
}
public SomeMethod()
{
var localOrNetwork = this.factory.Create(somethingDescribingWhatCallToMake)
localCalOrNetwork.SomeMethod();
}
}
So there is no place for decorator/interceptor.
Like others described I would use interceptors for cross cutting concerns - logging, auditing, caching, security and so on.
A dynamic proxy can be useful for implementing aspects of behaviour that apply across a complete system or sub-system. If you had 15 services each with 20 methods that need the same behaviour applied to them (security check, remoting, logging, ..., or sniffing - as in your example) then a dynamic proxy can be used to implement the behaviour once. Using delegation you can achieve the same result but with much more boilerplate code (300 times more using my numbers.)
Repetitive boilerplate code increases the amount of maintenance work involved in making a change, and makes certain types of structural change much more expensive (and less likely to happen.)
Dynamic proxies also have some disadvantages - the code is more complicated than for (a single use of) delegation. There can also be differences in performance characteristics that mean a trade-off needs to be made between performance and maintainability in those rare cases where the performance overhead is significant.
I think the idea with Dynamic Proxy is that it is really good for cross cutting concerns. Things where the underlying object graph does not affect the behavior you are trying to insert. Something like logging or policy enforcement of every function.