我在.NET Core中寻找RealProxy
替换,而issue将我转发到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...
这是正确的方法吗?
答案 0 :(得分:4)
您说得对,除了将生成的IFoo
强制转换为已知代理类型(FooProxy
)并在FooProxy
上使用自定义方法或属性之外,没有其他选择。没有公共API来添加构造函数参数或返回代理作为实现类型。但是,DispatchProxy.Create()
将返回FooProxy
子类的实例,其类型在运行时通过反射和IL发射生成。
如果您正在寻找快速包装实现并替换接口方法/虚拟方法的其他方法,我建议使用模拟框架(FakeItEasy,Moq,NSubstitute等)。
答案 1 :(得分:1)
您需要创建自己的继承自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 == 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
}
使用您的示例
var proxy=AopAction<IFoo>.Create(new FooImpl());