3

Is it possible to inject dependency into PostSharp aspect? I'd like to create NavigateBackAspect - something like that:

[PSerializable]
class NavigateBackAspect : OnMethodBoundaryAspect
{
    private readonly INavigationService _navigationService;

    public NavigateBackAspect(INavigationService navigationService)
    {
        _navigationService = navigationService;
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        base.OnExit(args);
        var viewModel = args.Instance as Shared.ViewModel.ViewModel;

        if (viewModel != null)
        {
            viewModel.Dispose();
            _navigationService.GoBack();
        }
    }
}

However I've read that constructor/parameter injection is not possible because constructor is called just once after compilation. Are there any workarounds?

fex
  • 3,488
  • 5
  • 30
  • 46
  • 1
    An answer to this question has been given here: http://stackoverflow.com/a/23535219/74435 – Gael Fraiteur Jun 22 '14 at 10:39
  • @GaelFraiteur That has nothing to do with this question. However, fex, you should probably reword the question without using the phrase 'dependency injection' because that usually refers to various IoC frameworks. – GregRos Jun 22 '14 at 10:44
  • Correct. Mental conflicts -- I just happened to review this response. But what about that: http://doc.postsharp.net/##consuming-dependencies – Gael Fraiteur Jun 22 '14 at 15:06

1 Answers1

3

This kind of thing is not possible mainly because attributes in general and aspects in particular can only have constant expressions in the constructor.

The constructor is called once per aspected target during compilation time. After this happens, the aspect is serialized (along with any internal data it may contain). It is deserialized during runtime, which means the constructor is not called at all. But there is no reason for it to be called; attribute constructors can only contain constant data that isn't liable to change. See about aspect lifetime here.

However, every aspected target still has its own instance of the aspect. This means you can do this during runtime initialization. You have a few options:

  1. Supply a string key parameter to the constructor, and then during runtime look up the appropriate object using the key (from a shared dictionary).
  2. Rely on the aspected type to have a property or field containing the object, and access it through reflection. It's recommended you do this during runtime initialization because reflection can cause performance problems.
GregRos
  • 8,667
  • 3
  • 37
  • 63