【问题标题】:Using compile-time aspects to implement abstract interfaces使用编译时方面来实现抽象接口
【发布时间】:2015-02-28 18:49:49
【问题描述】:

据我了解,所有编译时 .NET 面向方面的编程框架(例如 PostSharp 或 Fody)只能处理已经成功编译的代码。

如果您想使用这些框架中的方面来实现抽象接口的成员,这会带来障碍,因为被修改的类要到构建后步骤之后才能实现接口。如果由于缺少接口而导致编译阶段失败,则构建后步骤永远不会运行。

例如,编写 WPF MVVM 应用程序时,我的视图模型有一个抽象接口。接口规定视图模型必须实现一个命令,例如:

using System.Windows.Input
public interface ITestVM
{
  ICommand SomeCommand { get; }
}

我想创建这个视图模型抽象接口的具体实现,使用 Commander.Fody 来实现 ICommand 实例。这是我尝试过的:

using Commander;
public class TestVM : ITestVM
{
  [OnCommandCanExecute("SomeCommand")]
  private bool SomeCommandCanExecute()
  {
    return true;
  }

  [OnCommand("SomeCommand")]
  private void SomeCommandExecute()
  {
  }
}

这会产生错误消息“'TestVM' does not implement interface member 'ITestVM.SomeCommand'”

我相信 Commander.Fody 创建一个名为 SomeCommand 的 ICommand 实例,但它永远没有机会这样做。

有没有办法使用编译时面向方面的框架来实现抽象接口?我读过“AOP.NET”一书,编译时编织部分(第 183-190 页)没有讨论这种限制。

【问题讨论】:

  • 您可以做的是让 AOP 框架注入整个接口,而不仅仅是实现。但这可能会导致您的代码中出现其他问题,因为您可能在某个地方期望 TestVM 来实现 ITestVM,而编译器会抱怨那里
  • 可以将一些对象转换为接口,即使它没有实现它(在编译时)。所以你可以通过将 TestVM 转换为 ITestVM 来解决这个问题。

标签: .net mvvm aop fody


【解决方案1】:

这是 PostSharp 和 Fody 等工具的当前已知限制,因为它们是编译后编织器,而不是编译时编织器。

最好的方法是实现一个属性,您可以使用该属性作为标记来指示类应该由织布工修改。然后在您的编织器中,您必须将接口和实现添加到标记的类型。

PropertyChanged 对 ImplementPropertyChangedAttribute 做了类似的事情

【讨论】:

  • 好的。我可以看到,对于 INotifyPropertyChanged 等广泛使用的接口,这将是一种合理的方法。就我而言,这是一个特定于类的接口(事实上,在实际使用中,我将拥有不止一个命令),所以我认为如果每个命令都需要更多的工作来实现,我会否定 Commander.Fody 的好处比我手动滚动命令的效果要好。
  • 我刚刚注意到您区分了“编译后编织器”和“编译时编织器”。那是故意的吗?从 Groves 的“.NET 中的 AOP”第 7 章中,我熟悉了运行时和编译时编织之间的区别,但它将编译时和编译后时间视为同义词。如果有另一类织布机本质上更适合我描述的问题,我想了解一下。
  • @TimCrews 是的,我非常刻意地做出了这种区分。主要区别在于后编译必须修改 IL,而编译时可以处理原始源代码(C#/VB/F#/other)。异步状态机是一个很难修改 IL 的示例,但在编译之前很容易修改代码。 Try/Catch 是另一个在 IL 级别难以操作的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-01
  • 1970-01-01
  • 2010-12-14
  • 1970-01-01
  • 2012-07-17
  • 2011-11-20
  • 1970-01-01
相关资源
最近更新 更多