在C#中动态覆盖任何方法

时间:2017-03-04 17:59:09

标签: c# .net c#-4.0 system.reflection reflection.emit

我正在努力实现这样的目标

Player lebron = new Player("LeBron", 23, 2.03f);
lebron.Rings = 3;
lebron.Team = "Cleveland";

Player p = Proxy.For<Player>().Override("ToString", (target, argz) =>
{
     return target.name;
}).Proxify(lebron);

其中Override的第一个参数给出的任何方法都可以替换为Func<T, object[], object // where T is the same type use in For, in this case Player // and target is the T object (Player lebron in this case) and argz is the array of possible parameters

我想出这样做的方法是使用一个字典,方法名称为Key,并存储相应的Func<T, object[], object

使用Proxify,我将返回一个动态创建的新类型,扩展基类型T并将原始对象中的每个属性或字段复制到此新动态创建的类型。这个目前正在运作。

问题:如何覆盖用Override中给出的名称指定的任何函数,并且它的执行应该是给定的Func<T, object[], object>处理程序?

我试过了

foreach(MethodInfo mi in cloneType.GetMethods(FLAGS))
        {
            if (overr.ContainsKey(mi.Name)){
                Ops op;
                if(! overr.TryGetValue(mi.Name, out op)) continue;
                //tb.DefineMethodOverride(op.MethodInfo, mi);
                MethodBuilder mb = tb.DefineMethod(mi.Name,
                    MethodAttributes.Public
                    | MethodAttributes.HideBySig
                    | MethodAttributes.NewSlot
                    | MethodAttributes.Virtual
                    | MethodAttributes.Final,
                    CallingConventions.HasThis,
                    mi.ReturnType, op.GenericTypes);
                ILGenerator il = mb.GetILGenerator();

                il.Emit(OpCodes.Ldarg_0);


            }
        }

Ops op只是Func的包装器,它存储2个properyies,Func的MethodInfo和一个Type [],如果需要的话,我也可以访问Func本身。

我认为对于字典中的每个方法,我必须在我动态创建的类型中创建一个新方法,其中这个新方法体只是执行相关的Func,但我似乎无法使其工作。< / p>

一些帮助将不胜感激,如果您认为我的方向错误,请告诉我。

注意:我不能使用其他框架或图书馆,因为这是一个朋友的分配,我发现这个问题很有趣,我试图帮助他。

Proxy是一个我只用For方法创建的类,它返回一个可以调用Override的对象(此方法返回this)然后当调用Proxify时返回扩展T的内容复制了所有值,但有些方法像代码所说的那样重写。

1 个答案:

答案 0 :(得分:0)

如果Player的所有公共成员都是虚拟成员,您可以简单地派生一个包装类并将其用作代理的基类

我们假设PlayerToStringRun方法。然后delcare

public abstract class PlayerProxyBase : Player
{
    protected readonly Player _player;

    public PlayerProxyBase(Player player)
    {
        _player = player;
    }

    public override void Run()
    {
        _player.Run();
    }

    public override string ToString()
    {
        return _player.ToString();
    }
}

现在您可以像这样创建一个具体的Proxy类

public class MyPlayerProxy : PlayerProxyBase
{
    public MyPlayerProxy(Player player)
        : base(player)
    { }

    public override string ToString()
    {
        return _player.Name;
    }
}

动态创建代理:

Player p = new MyPlayerProxy(lebron);