1

I'm implementing a dotnet Maui app, and got to the point when I'd need some aspects to hanlde errors and certain responses. In the past, I implemented interceptors using Castle Windsor, but how can I do it in Maui?

The dev environment is Visual Studio 2022 v17.6.2 Maui versions:

Installed Workload Id      Manifest Version       Installation Source
---------------------------------------------------------------------
maui-ios                   7.0.86/7.0.100         VS 17.6.33723.286
android                    33.0.46/7.0.100        VS 17.6.33723.286
maui-windows               7.0.86/7.0.100         VS 17.6.33723.286
maui-maccatalyst           7.0.86/7.0.100         VS 17.6.33723.286
maccatalyst                16.4.7054/7.0.100      VS 17.6.33723.286
ios                        16.4.7054/7.0.100      VS 17.6.33723.286
maui-android               7.0.86/7.0.100         VS 17.6.33723.286

Targetframework: net7

Problem is that the built in DI resolver doesn't support interceptors (unless I missed something).

balintn
  • 988
  • 1
  • 9
  • 19

1 Answers1

1

Here's how I did it.

Choosing the DI provider

Dotnet built in one has no support for interceptors. Tried Castle Windsor, but the nuget package added a scary list of dependencies, so looked for something else. Then Autofac, and the dependency list was much friendlier (haven't actually checked the additional binary size in the deployed app though). Decided to use Autofac.

Steps

  • Added Autofac nuget package

  • Added Autofac container registration to MauiProgram.cs (based on https://stackoverflow.com/questions/73604106/how-to-use-autofac-with-net-maui)

      public static MauiApp CreateMauiApp()
      {
        var builder = MauiApp.CreateBuilder();
        builder
          .UseMauiApp<App>()
          .ConfigureFonts(fonts =>  { ... })
          .ConfigureContainer(new AutofacServiceProviderFactory(), autofacBuilder => {
              // Registrations
              // Don't call the autofacBuilder.Build() here - it is called behind
              // the scenes
              autofacBuilder.RegisterType<Logic>().As<ILogic>() // where Logic is the type to add the aspect to
                  .EnableClassInterceptors()
                  .InterceptedBy(typeof(LoggingAspect));  // LoggingAspect is the interceptor to implement logging
              autofacBuilder.RegisterType<MainPage>();  // See step below, had to add DI registration for the Maui MainPage
              autofacBuilder.RegisterType<LoggingAspect>();
          });
          ...
    
  • Added Autofac.Extensions.DependencyInjection nuget package

  • Created ILogic interface and Logic class (as demonstration, thi is the class to intercept)

  • Registered ILogic, Logic as a DI component in MauiProgram.cs with Autofac (see code sample above)

  • Registered MainPage with Autofac (see code sample above)

Added an aspect (see https://levelup.gitconnected.com/embracing-aspect-oriented-programming-in-net-2640f9ace519)

  • Install nuget package Autofac.Extras.DynamicProxy
  • Create logging aspect (LoggingAspect.cs)
  • Register interceptor for the class in DI registration (see code sample above)

At this point I was faced with intercepting both sync and async methods, and remembered it was not easy. Luckily I had my own library from before, added the nuget package BaseInterceptors and implemented the logging aspect based on Example 2 at https://www.nuget.org/packages/BaseInterceptors

balintn
  • 988
  • 1
  • 9
  • 19
  • An interesting result, possibly a problem: when interceptors are enabled (using autofacBuilder.RegisterType<...>As<...>.EnableInterfaceInterceptors(); even if none are actually assigned to any type), Visual Studio breaks on some native exception, displaying the message "No compatible code running on the thred". Just continuing seems to execute my dotnet code correctly, but there may be some issues underneath. – balintn Jun 17 '23 at 21:19
  • .EnableClassInterceptors() makes it better: when no interceptors are actually registered, it runs without an error. When I actually attach my interceptors, errors show again, will have to check if it is a problem with my code. Updating original answer to use EnableClassIntrceptors(). – balintn Jun 17 '23 at 21:24