3

我在 .NET 中制作了一个可移植类库 (PCL),碰巧在尝试抽象任何行为时,我面临一个非常常见的烦恼,即 .NET Framework对其类型和接口非常具有占有欲。通常会发现一个类型没有实现任何接口,或者当它实现时,接口是内部的。

当现有类型具有兼容的方法(相同的名称和签名)时,这相当容易:我一直在使用 ImpromptuInterface,如下所示:

nakedInstanceTheDoesNotImplementAnything.ActAs<MyBeautifulInterface>();

我得到了我想要的。透明且方便。

但是,当某些方法略有不同时该怎么办?

  • 不同的名字
  • 不同的调用站点:一个是属性getter,另一个是方法
  • 一些不同的方法,但只需稍作修改即可轻松适应它们。

通常,建议使用纯 OOP 方法,并告诉我们创建和适配器。但是当您必须适应复杂的类型层次结构时,这也可能非常繁琐和复杂,当您拥有 UIElement、Control、FrameworkElement 等庞大的类时更是如此……</p>

问题是:我可以让 ImpromptuInterface 克服这些类型的变化来动态创建适配器吗?

4

1 回答 1

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;
    }
}

但这需要做很多工作,因为您必须像处理已修改的调用一样处理未修改的调用。

有几个 prefabDynamicObjectImpromptuInterface已经移到了一个单独的库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>()

于 2014-03-08T03:08:45.137 回答