C#中使用反射的方法拦截 [英] Method Interception using Reflection in C#

查看:170
本文介绍了C#中使用反射的方法拦截的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个抽象类,它使用反射来查找构造函数中标有属性的字段,如下所示:

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
            }
        }
    }
}

我想做的是:

  1. 创建另一个属性,TrackedMethod
  2. 在构造函数中,在与 TrackedFields 相同的方式,找到所有标记为的方法跟踪方法
  3. 改变方法,当它被调用时,一个ATrackedObject 中的方法首先被调用,或者被调用完全替换该方法或通过向其中注入代码,但是在不破坏的情况下,至少可以看到原始内容方法调用是,包括参数
  4. 没有第三方库,并且应该兼容 .NET 3.5
  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

我已经看到许多 SE 线程讨论如何做到这一点,所有答案都依赖于能够使用第三方库 - 但是,似乎没有一个问题与我的用例完全匹配 - 我可以确保100% 需要跟踪方法的每个对象都将从进行跟踪的类继承.

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.

我不确定这是否可行,但我想知道既然像 PostSharp 和其他这样的 IoC/AOP 库存在,它们肯定必须通过某种机制运行 - 我认为 Reflection.Emit 发挥了作用 - 但是什么,以及如何?

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-调用

how-do-i-intercept-a-method-call-in-c(这很有帮助,但缺少如何实际注入代码的关键部分

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

拦截方法调用

有没有办法让这种技术(属性 -> 基类构造函数 -> 反射 -> 方法拦截)可行?

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

推荐答案

这样的东西能满足您的需求吗?

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");
}

这是通过一个简单的 Action 属性完成的,但它可以扩展为使用 Func<>

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

忘记包括用法和输出.

用法:

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

    Console.Read();
}

输出:

Tracking SomeMethod
Some Method Called

这篇关于C#中使用反射的方法拦截的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆