【问题标题】:Automatic adapter generation in .NET [closed].NET 中的自动适配器生成 [关闭]
【发布时间】:2015-10-10 01:35:34
【问题描述】:

我的应用程序有一个 C# 库 Baz.dll 引用 3rd-party(其他团队)库 Foo.dll,其中包含类 FooActuator,由 Baz 直接使用。我想通过声明一个接口IActuator 来打破这种依赖关系,并有一个控制器来实例化IActuator 的正确实现并将其发送到Baz。而且我无法更改Foo

问题是,这个场景有一堆类,我不想一直写adapter。我正在寻找这样的东西:

FooActuator real = new FooActuator();
IActuator adapter = BuildAdapter<IActuator>(real); // generates adapter for me
Baz.Process(adapter);

是否有提供此功能的库或 .NET 功能?我希望我可以复制或扩展一些东西(即已经生成了一些类和程序集),而不是从头开始使用 System.Reflection.Emit。

【问题讨论】:

  • 我不太明白你为什么需要适配器模式。为什么不能让FooActuator 实现IActuator 并使用(例如)IoC 容器?
  • 您是否正在寻找一种方法让FooActuator 表现得好像它继承自IActuator,即使它不在代码中?如果是这样,您是否有什么理由不想拥有FooActuator : IActuator
  • @TeaDrivenDev 感谢您的评论。我已经编辑了我的问题。确实缺少一个关键信息:Foo 来自另一个团队。我不能碰那个。拥有IActuator 的原因是允许像往常一样对Baz 进行单一测试。
  • 附带说明 - 如果您有另一个团队构建您需要使用的东西,但您无法使用通用抽象,您可能会遇到组织问题.
  • @TeaDrivenDev 我认为你假设太多了。有许多由不同团队、社区和组织提供的第三方库,它们有明确的、明确定义的目的,不需要抽象接口。这些库的使用者可以选择直接调用它,或者通过接口和适配器隔离调用。

标签: c# .net oop design-patterns f#


【解决方案1】:

我想,你可以看看Impromptu interface library。安装后,您可以执行以下操作:

FooActuator real = new FooActuator();
IActuator adapter = Impromptu.ActLike<IActuator>(real);
Baz.Process(adapter);

即兴接口库实际上做了什么,它在运行时使用反射发射创建一个新类型,新类型实现IActuator接口。当一些协作者从IActuator接口调用方法时,这些调用被委托给FooActuator封装的实例(这意味着FooActuatorIActuator中的方法名称必须匹配)。

【讨论】:

    【解决方案2】:

    听起来您正在掌握控制反转,并且由于未知原因,不想一路走到那里。在我看来,最直接的方法是让Foo 引用Baz,并且你的FooActuator 符合接口IActuator

    public class FooActuator : IActuator
    ...
    

    这需要从Foo.dllBaz.dll 的引用(您已反转控制)。您可以通过一些依赖注入更进一步,以便 IActuators 可以在运行时解析,使用类似 Activator.CreateInstance() 或 LINQ to Expressions 的东西(它应该会更好地执行并为您提供一些更强大的选项):

    Type iActuatorType = Type.GetType(fqnOfClassAndAssembly);
    Func<IActuator> tActuatorInstance = null;
    if (t != null)
        // tActuatorInstance will be instantiated after this call, if the type can be found
        tActuatorInstance = Expression.Lambda<Func<IActuator>>(Expression.New(iActuatorType)).Compile();
    

    这将使您无需在编译时知道IActuator 的每个实现,但仍然保持您尝试“适应”到IActuator 的任何类肯定包含您期望的方法。换句话说,这将强制将适配器逻辑写入类本身的实现 - 如果您真的有一个(封闭源代码/不可修改的)类,仍然可以允许您使用适配器模式需要它:

    public class BatActuatorAdapter : BatActuator, IActuator
    // methods and properties in here to manipulate BatActuator, which you wouldn't otherwise be able to manipulate.
    

    【讨论】:

    • 谢谢,但我无法更改Foo(我已编辑我的问题以使其更清楚)。所有适配器的实现都必须是普通的包装器,这就是我寻找代码生成解决方案的原因。
    猜你喜欢
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 2015-05-11
    • 2010-11-06
    • 2013-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多