c# - 当实现略有不同时如何使用 DuckTyping?

标签 c# .net adapter impromptu-interface

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

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

nakedInstanceTheDoesNotImplementAnything.ActAs<MyBeautifulInterface>();

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

但是,有些方法略有不同怎么办?

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

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

问题是:我能否使 ImpromptuInterface 克服类型中的这些变化以动态创建适配器?

最佳答案

所以 ImpromtuInterface使用 DLR,基本上当您调用 ActLike() 时,它会发出并缓存该接口(interface)的代理,并将其包装在您的对象周围。

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

但这需要大量工作,因为您必须像处理修改后的调用一样处理未修改的调用。

有几个预制件DynamicObjectImpromptuInterface我已经搬到了一个单独的图书馆 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>()

关于c# - 当实现略有不同时如何使用 DuckTyping?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21613651/

相关文章:

c# - iText 7.0.4.0 - PdfWriter 为某些 PDF 文件输入生成损坏的 PDF

c# - 从 LINQ 语句获取单个结果

c# - 为什么应该在任务 C# 中使用结果?

java - 从 Adapter 中刷新整个 RecyclerView

java - Java 方法中的多个类型参数,包括现有类和原始数据类型

Java - 在自定义适配器中创建对两个模型的引用

c# - 使用参数创建自定义异常

C# 如何找到类的非创建对象?

c# - WPF .NET 应用程序崩溃、组合框和菜单事件未在装有 Windows 10 Creators Update、.NET 4.7 或 KB4034658 的平板电脑上触发

c# - 如何使用 .Net/Parse.com 发送 API 凭据和用户名/密码? (PHP 到 C#)