Hallow
Hallow

Reputation: 1070

Override Any Method Dynamically in C#

i am trying to achieve something like this

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

where any method given by the first parameter of Override can be replaced by a 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

The way i figured out to do this is to have a Dictionary with the method name as Key and storing the corresponding Func<T, object[], object.

With Proxify i am returning a new Type that was created dynamically, extending the base type T and copying every property or fields from the original object to this newly dynamically created one. This is working for now.

Problem: How to i Override any function specified with the name given in Override, and its execution should be the Func<T, object[], object> handler given ?

I have tried

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 is just a wrapper for the Func, it stores 2 properyies, the MethodInfo of the Func, and a Type[] for it GenericTypes, i can also access the Func itself if needed.

I think that for each method in the dictionary i must create a new method in my dynamically created type, where this new methods body is only the execution of the associated Func, but i can't seem to make this work.

Some help would be appreciated, and if you think i'm in the wrong direction please advise me.

Note: I can't use other Frameworks or Libraries as this is a Friends assigment and i found this problem intriguing to implement and i am trying to help him.

Proxy is a class that i created with only the For method which returns an object where you can call Override (this method returns this ) and then when Proxify is called it returns something that extends T with all values copied but some methods overriden like the code tells.

Upvotes: 3

Views: 3176

Answers (1)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112782

If all the public members of Player are virtual, you could simply derive a wrapper class and use it as a base class for proxies

Let's assume that Player has a ToString and a Run method. Then 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();
    }
}

Now you can create a concrete Proxy class like this

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

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

Create a proxy dynamically:

Player p = new MyPlayerProxy(lebron);

Upvotes: 1

Related Questions