1

As I understand it, all compile-time .NET aspect-oriented-programming frameworks (such as PostSharp or Fody) can only process code that has already successfully compiled.

This presents an obstacle if you want to use an aspect from these frameworks to implement members of an abstract interface, because the class being modified would not implement the interface until after the post-build step. The post-build step never gets to run if the compilation stage fails because of the missing interface.

For example, writing an WPF MVVM application, I have an abstract interface for my view model. The interface dictates that the view model must implement a command, e.g.:

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

I would like to create a concrete implementation of this view model abstract interface, using Commander.Fody to implement the ICommand instance. Here's what I tried:

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

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

This produces the error message "'TestVM' does not implement interface member 'ITestVM.SomeCommand'"

I believe that Commander.Fody would create an ICommand instance named SomeCommand, but it never gets a chance to do so.

Is there any way to use compile-time aspect-oriented frameworks to implement abstract interfaces? I've read the book "AOP.NET", and no such limitation is discussed in the section on compile-time weaving (pp 183-190).

Tim Crews
  • 435
  • 5
  • 13
  • What you could do is have the AOP framework inject the whole interface instead of just the implementation. But that would probably lead to other problems in your code because somewhere you probably *expect* TestVM to implement ITestVM and the compiler will complain *there*. – nvoigt Feb 10 '15 at 19:51
  • It is possible to cast some object to an interface though, even if it doesn't implement it (at compile time). So you could solve that problem by casting TestVM to ITestVM. – Daniel Sklenitzka Feb 13 '15 at 07:54

1 Answers1

0

This is a current known limitation of tools like PostSharp and Fody as they are post-compiler weavers, not compile-time weavers.

The best way to do it is to implement an attribute that you can use as a marker to signal a class should be modified by a weaver. Then in your weaver you would have to add the interface, and the implementation to the type marked.

PropertyChanged does a similar thing with the ImplementPropertyChangedAttribute

Cameron MacFarland
  • 70,676
  • 20
  • 104
  • 133
  • OK. I can see that would be a reasonable approach for a widely-used interface such as INotifyPropertyChanged. In my case, this is a class-specific interface (and in fact, in real usage I would have far more than one command), so I think I would be negating the benefit of Commander.Fody if each command required more work to implement than it would have if I had rolled the command by hand. – Tim Crews Mar 02 '15 at 16:57
  • I just noticed that you drew a distinction between "post-compiler weavers" and "compile-time weavers". Was that intentional? From Groves' "AOP in .NET" Chapter 7, I am familiar with the distinction between run-time and compile-time weaving, but it treats compile-time and post-compile time as synonymous. If there is another category of weaver that is inherently better suited to the problem I described, I would like to learn about it. – Tim Crews Mar 02 '15 at 20:10
  • @TimCrews Yes I made that distinction very deliberately. The major difference is that post-compile has to modify IL whereas compile-time can deal with the original source (C#/VB/F#/other). Async state machines is an example where it's hard to modify the IL, but would be easy to modify the code before compiling. Try/Catch is another thing that's hard to manipulate at the IL level. – Cameron MacFarland Mar 03 '15 at 01:15