我正在.NET中制作一个便携式类库(pcl),而且碰巧的是,当试图抽象任何行为时,我会面临一个非常常见的烦恼。具有其类型和界面非常占有性。找到类型的类型通常不会实现任何接口,或者当它执行时,接口是内部的。
现有类型具有兼容方法(相同的名称和签名)时,这很容易:我一直在使用这样的即兴界面:
nakedInstanceTheDoesNotImplementAnything.ActAs<MyBeautifulInterface>();
我得到了我想要的。透明且方便。
但是,当某些方法略有不同时该怎么办?
- 不同的名称
- 不同的呼叫网站:一个是属性Getter,另一个是方法
- 某些不同的方法不同,但在它们之间易于适应。
通常,建议采用纯OOP方法,并告诉我们要创建和适配器。但是当您必须调整复杂的类型层次结构时,这可以是确实很乏味且复杂的,当您拥有诸如UIELEMENT,CONTROL,CONTROL,FRAFERWORKEELEMENT ...
问题是:我可以使即兴结界在类型中克服这些变化以动态创建适配器吗?
因此, ImpromtuInterface
使用dlr,基本上是当您调用actlike()时,它会发出并缓存该接口的代理,并将其包裹在您的对象上。
public class Proxy:IMyInterface {
dynamic target;
public int Foo(){
return (int)target.Foo()
}
}
由于这是一个动态的调用,因此您实际上在目标上实际上没有方法,并且idynamicmetaobjectsprovider是自定义为System.Dynamic.DynamicObject
的最受欢迎的方法。
public class RoughDynamicAdapter:DynamicObject{
public override bool TryInvokeMember(InvokeMemberBinder binder,
Object[] args,
out Object result){
if(binder.Name == "Foo"){
result = /* do your own logic */
return true;
}
result = null;
return false;
}
}
,但这是很多工作,因为它必须像修改后的调用一样处理非修改的调用。
ImpromptuInterface
中有几个Prefab DynamicObject
s,我搬到了单独的库Dynamitey。
特别是,BaseForwarder
听起来像您想要的,因为与其传递所有逻辑,而是将消息转发到目标对象已被实现为基本功能。
public class DynamicAdapter:Dynamitey.DynamicObjects.BaseForwarder {
public DynamicAdapter(object target):base(target){
}
public override bool TryInvokeMember(InvokeMemberBinder binder,
Object[] args,
out Object result){
var newName = binder.Name;
if(newName == "Foo"){
result = Dynamic.InvokeMember(CallTarget, "Bar", args)
return true;
}
//else pass them method on as it was called
return base.TryInvokeMember(binder, args, out result)
}
}
然后使用它是new DynamicAdapter(myObject).ActLike<IMyInterface>()