如果你有一辆实现IVehicle的类车,并且你想将它包装在一个装饰器中,该装饰器将所有的呼叫转发给汽车并计算它们,你会怎么做?
在Ruby中,我可以在没有任何方法的情况下构建装饰器,并使用method_missing将所有调用转发给car对象。
在Java中,我可以构建一个Proxy对象,通过一种方法运行所有代码,然后再转发它。
我能用C#做些类似的事吗?
更新
基于answeres和我读过的关于System.Reflection.Emit的内容,应该可以编写一个与此类似的方法:
Type proxyBuilder(Type someType, delagate functionToBeApplied, Object forward)
其中type实现someType的所有接口,执行functionToBeApplied,然后在返回其返回时将方法调用转发给object。
是否有一些lib可以做到这一点,还是我必须自己编写?
答案 0 :(得分:4)
对于代理,你可以查看“RealProxy”,如果你想使用标准类型,虽然使用它有点麻烦(并且它要求你的类继承MarshalByRefObject)。
public class TestProxy<T> : RealProxy where T : class
{
public T Instance { get { return (T)GetTransparentProxy(); } }
private readonly MarshalByRefObject refObject;
private readonly string uri;
public TestProxy() : base(typeof(T))
{
refObject = (MarshalByRefObject)Activator.CreateInstance(typeof(T));
var objRef = RemotingServices.Marshal(refObject);
uri = objRef.URI;
}
// You can find more info on what can be done in here off MSDN.
public override IMessage Invoke(IMessage message)
{
Console.WriteLine("Invoke!");
message.Properties["__Uri"] = uri;
return ChannelServices.SyncDispatchMessage(message);
}
}
或者你也可以从Castle获得“DynamicProxy”..根据我的经验,它的效果会更好。
如果你使用其中一个,你不会有必要获得很好的性能,我主要用于可能在一开始可能很慢的通话中。但你可以尝试一下,如果你想。
Marc的解决方案将有更好的表现。
答案 1 :(得分:2)
不幸的是,C#中没有mixin支持。所以你需要实现所有方法,或者使用一些重要的反射来执行它。另一种选择是(可选的)代理/装饰器基类...
abstract class FooBase : IFoo {
protected FooBase(IFoo next) {this.next = next;}
private readonly IFoo next;
public virtual void Bar() { // one of the interface methods
next.Bar();
}
public virtual int Blop() { // one of the interface methods
return next.Blop();
}
// etc
}
然后
class SomeFoo : FooBase {
public SomeFoo(IFoo next) : base(next) {}
public override void Bar() {...}
}
注意FooBase
的使用是严格可选的;任何IFoo都是允许的。