我正在.NET中创建一个可移植类库(PCL),当我尝试抽象任何行为时,我遇到了.NET Framework 非常普遍的烦恼,它的类型和接口非常占有欲即可。通常发现一个类型没有实现任何接口,或者当它发生时,接口是内部的。
当现有类型具有兼容的方法(相同的名称和签名)时,它很容易:我一直在使用ImpromptuInterface:
nakedInstanceTheDoesNotImplementAnything.ActAs<MyBeautifulInterface>();
我完全得到了我想要的东西。透明而且方便。
但是,当某些方法略有不同时该怎么办?
通常,建议采用纯OOP方法,并告知我们创建和适配器。 但是当你必须适应复杂的类型层次结构时,这可能非常繁琐且复杂,当你拥有像UIElement,Control,FrameworkElement这样的巨大类时更是如此......
问题是:我是否可以使ImpromptuInterface克服类型中的变化以动态创建适配器?
答案 0 :(得分:2)
所以ImpromtuInterface
使用DLR,基本上当你调用ActLike()时它会发出并缓存该接口的代理,然后将它包装在你的对象周围。
public class Proxy:IMyInterface {
dynamic target;
public int Foo(){
return (int)target.Foo()
}
}
因为它是一个动态调用,所以你实际上并没有在目标上使用该方法,如果它和IDynamicMetaObjectProvider最受欢迎,可以自定义为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;
}
}
但这需要做很多工作,因为你必须像修改后的调用那样处理非修改的调用。
DynamicObject
中有几个预制ImpromptuInterface
我已移至另一个库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>()