如何将现有对象实例包装到 DispatchProxy 中?
How to wrap existing object instance into DispatchProxy?
我正在 .NET Core 中寻找 RealProxy
替代品,而这个 issue forwards me to DispatchProxy
。
它有简单的 API,但不清楚如何将 现有 对象包装到代理中。
例如,具有此接口:
interface IFoo
{
string Bar(int boo);
}
和这个实现:
class FooImpl : IFoo
{
public string Bar(int boo)
{
return $"Value {boo} was passed";
}
}
如何得到我想要的?
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);
}
}
由于DispatchProxy
后代必须有无参数构造函数,我唯一的想法就是发明一些方法,像这样:
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);
}
}
并这样使用它:
var fooInstance = new FooImpl();
var proxy = DispatchProxy.Create<IFoo, FooProxy>();
((FooProxy)proxy).SetTarget(fooInstance);
// the rest of code...
这是正确的方法吗?
你是对的,除了将生成的 IFoo
转换为已知代理类型 (FooProxy
) 并使用自定义方法或 属性 FooProxy
。没有 public API 添加构造函数参数或 return 代理作为实现类型。但是,DispatchProxy.Create()
将 return 是 FooProxy
的子类实例,其类型是在运行时通过反射和 IL 发射生成的。
如果您正在寻找其他方法来快速包装实现并替换接口方法/虚拟方法,我建议改用模拟框架(FakeItEasy、Moq、NSubstitute 等)。
您需要创建自己的通用 class,它继承自 DispatchProxy 并拥有自己的静态 Create,它具有来自类型 target 的额外参数。
例子
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 == null ? 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
}
使用你的例子
var proxy=AopAction<IFoo>.Create(new FooImpl());
我正在 .NET Core 中寻找 RealProxy
替代品,而这个 issue forwards me to DispatchProxy
。
它有简单的 API,但不清楚如何将 现有 对象包装到代理中。
例如,具有此接口:
interface IFoo
{
string Bar(int boo);
}
和这个实现:
class FooImpl : IFoo
{
public string Bar(int boo)
{
return $"Value {boo} was passed";
}
}
如何得到我想要的?
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);
}
}
由于DispatchProxy
后代必须有无参数构造函数,我唯一的想法就是发明一些方法,像这样:
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);
}
}
并这样使用它:
var fooInstance = new FooImpl();
var proxy = DispatchProxy.Create<IFoo, FooProxy>();
((FooProxy)proxy).SetTarget(fooInstance);
// the rest of code...
这是正确的方法吗?
你是对的,除了将生成的 IFoo
转换为已知代理类型 (FooProxy
) 并使用自定义方法或 属性 FooProxy
。没有 public API 添加构造函数参数或 return 代理作为实现类型。但是,DispatchProxy.Create()
将 return 是 FooProxy
的子类实例,其类型是在运行时通过反射和 IL 发射生成的。
如果您正在寻找其他方法来快速包装实现并替换接口方法/虚拟方法,我建议改用模拟框架(FakeItEasy、Moq、NSubstitute 等)。
您需要创建自己的通用 class,它继承自 DispatchProxy 并拥有自己的静态 Create,它具有来自类型 target 的额外参数。
例子
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 == null ? 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
}
使用你的例子
var proxy=AopAction<IFoo>.Create(new FooImpl());