Method Interception using Reflection in C#

余生颓废 提交于 2020-01-23 17:04:45

问题


I wrote an abstract class that uses reflection to find fields marked with an Attribute in the constructor, like this:

[AttributeUsage(AttributeTargets.Field)]
public class TrackedField : Attribute {}

public class ATrackedObject {
    public ATrackedObject() {
        Type objType = this.GetType();
        foreach(FieldInfo f in objType.GetFields()) {
            if(f.IsDefined(typeof(TrackedField)), false)) {
                //Add field to list to keep tabs on periodically
            }
        }
    }
}

What I would like to do, is:

  1. Create another attribute, TrackedMethod
  2. In the constructor, in the same fashion as with the TrackedFields, find all methods tagged with TrackedMethod
  3. Change the method so that when it gets called, a method inside ATrackedObject gets called first or instead, either by replacing the method entirely or by injecting code into it, but without breaking the ability to at least see what the original method call was, including parameters
  4. No third-party libaries, and should be .NET 3.5 compatible

I have seen a number of SE threads discussing how to do this, and all of the answers relied on being able to use a third party library - however, none of the questions seemed to match my use case exactly - I can ensure 100% that every object that needs to have methods tracked will inherit from the class that does the tracking.

I don't know for sure this is possible, but I am wondering since IoC/AOP libraries like PostSharp and others exist, surely they must operate by some kind of mechanism - I assume Reflection.Emit plays a part - but what, and how?

Here are some similar questions, which did not have what seemed to me to be answers to my specific scenario, or relied on third party libraries:

custom-attribute-to-process-info-before-a-method-is-called

how-do-i-intercept-a-method-call-in-c (this was helpful, but missing the crucial component of how to actually inject code

intercept-method-calls

Is there a way to make this technique (Attribute -> Base Class Constructor -> Reflection -> Method Interception) viable?


回答1:


Could something like this work for what you need?

[AttributeUsage(AttributeTargets.Field)]
public class TrackedField : Attribute { }

public class ATrackedObject
{
    public ATrackedObject()
    {
        Type objType = this.GetType();
        foreach (FieldInfo f in objType.GetFields())
        {
            if (f.IsDefined(typeof(TrackedField), false)) {
                if (f.FieldType == typeof(Action))
                {
                    var currentValue = f.GetValue(this) as Action;
                    Action newValue = () =>
                    {
                        Console.WriteLine($"Tracking {f.Name}");
                        currentValue.Invoke();
                    };

                    f.SetValue(this, newValue);
                }
            }
        }
    }

    [TrackedField]
    public Action SomeMethod = () => Console.WriteLine("Some Method Called");
}

this is done with a simple Action property but it could be extended to use Func<>

edit: forgot to include usage and output.

usage:

static void Main(string[] args)
{
    var obj = new ATrackedObject();
    obj.SomeMethod();

    Console.Read();
}

output:

Tracking SomeMethod
Some Method Called


来源:https://stackoverflow.com/questions/46165707/method-interception-using-reflection-in-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!