How do I wrap an existing instance of an object in a DispatchProxy?

I am looking for a replacement RealProxy

in .NET Core and this issue redirects me to DispatchProxy

.

It has a simple API, but it is not clear how to wrap an existing object in a proxy. For example, having this interface:

interface IFoo
{
    string Bar(int boo);
}

      

and this implementation:

class FooImpl : IFoo
{
    public string Bar(int boo)
    {
        return $"Value {boo} was passed";
    }
}

      

how do i get what i want?

class Program
{
    static void Main(string[] args)
    {
        var fooInstance = new FooImpl();
        var proxy = DispatchProxy.Create<IFoo, FooProxy>();

        var s = proxy.Bar(123);

        Console.WriteLine(s);
    }
}

class FooProxy : DispatchProxy
{
    protected override object Invoke(MethodInfo targetMethod, object[] args)
    {
        return targetMethod.Invoke(/* I need fooInstance here */, args);
    }
}

      

Since DispatchProxy

descendants must have a parameterless constructor, the only idea I have is to invent some kind of method, like this:

class FooProxy : DispatchProxy
{
    private object target;

    public void SetTarget(object target)
    {
        this.target = target;
    }

    protected override object Invoke(MethodInfo targetMethod, object[] args)
    {
        return targetMethod.Invoke(target, args);
    }
}

      

and use it like this:

var fooInstance = new FooImpl();
var proxy = DispatchProxy.Create<IFoo, FooProxy>();

((FooProxy)proxy).SetTarget(fooInstance);

// the rest of code...

      

Is this the correct approach?

+4


source to share


2 answers


You are correct that there is no other option here than to generate the generated IFoo

proxy ( FooProxy

) to a known type and use your own method or property on FooProxy

. There is no public API for adding constructor arguments or returning a proxy as an implementation type. However, it DispatchProxy.Create()

will return an instance of the subclass FooProxy

whose type is generated at runtime through reflection and IL radiation.



If you are looking at other ways to quickly port implementation and replace interface / virtual methods, I suggest using fake frameworks (FakeItEasy, Moq, NSubstitute, etc.) instead.

+4


source


You need to create your own Generic class that inherits from DispatchProxy and has its own static Create, which has an additional parameter from the target type.

example

public class AopAction<T>:DispatchProxy
{
  #region Private Fields
  private Action<MethodInfo,object[],object> ActAfter;
  private Action<MethodInfo,object[]> ActBefore;
  private Action<MethodInfo,object[],Exception> ActException;
  private T Decorated;
  #endregion Private Fields

  #region Public Methods
  public static T Create(T decorated,Action<MethodInfo,object[]> actBefore = null,Action<MethodInfo,object[],object> actAfter = null,Action<MethodInfo,object[],Exception> actException = null)
  {
    object proxy = Create<T,AopAction<T>>();
    SetParameters();
    return (T)proxy;
    void SetParameters()
    {
      var me = ((AopAction<T>)proxy);
      me.Decorated = decorated == default ? throw new ArgumentNullException(nameof(decorated)) : decorated;
      me.ActBefore = actBefore;
      me.ActAfter = actAfter;
      me.ActException = actException;
    }
  }
  #endregion Public Methods

  #region Protected Methods
  protected override object Invoke(MethodInfo targetMethod,object[] args)
  {
    _ = targetMethod ?? throw new ArgumentException(nameof(targetMethod));

    try
    {
      ActBefore?.Invoke(targetMethod,args);
      var result = targetMethod.Invoke(Decorated,args);
      ActAfter?.Invoke(targetMethod,args,result);
      return result;
    }
    catch(Exception ex)
    {
      ActException?.Invoke(targetMethod,args,ex);
      throw ex.InnerException;
    }
  }
  #endregion Protected Methods
}

      



use your example

var proxy=AopAction<IFoo>.Create(new FooImpl());

      

0


source







All Articles