title: Autofac register multiple decorators of multiple services
body: <p>I have the following services in my application:<br/></p>
  
  <pre><code>public interface IDecorableService
  {
  
  }
  
  public interface IServiceDecorator
  {
  
  }
  
  public interface ICommentService
  {
     Task&lt;Comment&gt; AddAsync(Comment comment);
  }
  
  public class CommentService : ICommentService, IDecorableService
  {
     public async Task&lt;Comment&gt; AddAsync(Comment comment)
     {
        //some code
     }
  }
  
  [DecorationOrder(Order = 1)]
  public class EventLoggingCommentService : ICommentService, IServiceDecorator
  {
     private readonly ICommentService _commentService;
  
     private readonly IEventLoggerService _eventLoggerService;
  
     public EventLoggingCommentService(ICommentService commentService, IEventLoggerService eventLoggerService)
     {
        _commentService = commentService;
        _eventLoggerService = eventLoggerService;
     }
  
     public async Task&lt;Comment&gt; Add(Comment comment)
     {
        comment = await _commentService.AddAsync(comment);
        //log comment added event by eventLogService
        return comment;
     }
  }
  
  [DecorationOrder(Order = 2)]
  public class NotificationCommentService : ICommentService, IServiceDecorator
  {
     private readonly ICommentService _commentService;
  
     private readonly INotificationService _notificationService;
  
     public NotificationCommentService(ICommentService commentService, INotificationService notificationService)
     {
        _commentService = commentService;
        _notificationService = notificationService;
     }
  
     public async Task&lt;Comment&gt; Add(Comment comment)
     {
        comment = await _commentService.AddAsync(comment);
        //send notifications about comment by notificationService
        return comment;
     }
  }
  </code></pre>
  
  <p>I also have some services which are similar to the CommentService (for example, PostService) and some services which not to be decorated.</p>
  
  <p>I'm using Autofac and I need to register decorators for each service which need to be decorated (in the specified order) and register other services as self. I don't know. how many services need to be decorated.</p>
  
  <p>I tried to do the following:</p>
  
  <pre><code>public class BusinessLayerModule : Module
  {
     private readonly object[] _tags;
  
     private readonly string[] _skippingInterfaces = new string[]
     {
        nameof(IDecorableService),
        nameof(IDecoratedService)
     };
  
     public BusinessLayerModule(List&lt;object&gt; tags)
     {
        _tags = tags?.ToArray();
     }
  
     protected override void Load(ContainerBuilder builder)
     {
        Assembly assembly = Assembly.GetExecutingAssembly();
  
        //Registering non-decorable services
        builder.RegisterAssemblyTypes(assembly)
                  .Where(t =&gt; t.IsClass &amp;&amp; !t.IsAbstract &amp;&amp; t.Name.EndsWith("Service") &amp;&amp; !t.GetInterfaces().Any(x =&gt; _skippingIntefaces.Contains(x.Name)))
                  .AsSelf()
                  .InstancePerMatchingLifetimeScope(_tags);
  
        //Registering decorable services
        RegisterDecorators(builder, assembly, _tags);
     }
  
     private void RegisterDecorators(ContainerBuilder builder, Assembly assembly, object[] tags)
     {
        //Getting all services which can be decorated
        List&lt;Type&gt; decorableServices = assembly.GetTypes().Where(t =&gt; t.IsClass &amp;&amp; !t.IsAbstract &amp;&amp; t.Name.EndsWith("Service")
                                                                        &amp;&amp; t.GetInterface(nameof(IDecorableService)) != null
                                                                        &amp;&amp; t.GetInterface(nameof(IServiceDecorator)) == null).ToList();
  
  
          foreach (Type type in decorableServices)
          {
              //Getting the base interface, for example, ICommentService
              Type baseType = type.GetInterfaces().First(x =&gt; x.Name.EndsWith(type.Name));
  
              MethodInfo mi = this.GetType().GetMethod(nameof(RegisterDecoratedService), BindingFlags.NonPublic | BindingFlags.Instance);
              MethodInfo gmi = mi.MakeGenericMethod(baseType, type);
              gmi.Invoke(this, new object[] {builder, assembly, baseType, type, tags});
          }
      }
  
     private void RegisterDecoratedService&lt;TInterface, TImplementation&gt;(ContainerBuilder builder, Assembly assembly, Type baseType, Type implType, object[] tags)
      {
          //Getting all decorators of the service ordering by decoration order
          List&lt;Type&gt; decorators = assembly.GetTypes().Where(t =&gt; t.IsClass &amp;&amp; !t.IsAbstract &amp;&amp; t.Name.EndsWith("Service")
                                                                 &amp;&amp; t.GetInterface(baseType.Name) != null
                                                                 &amp;&amp; t.GetInterface(nameof(IServiceDecorator)) != null)
              .OrderBy(t =&gt;
              {
                  DecorationOrderAttribute order = t.GetCustomAttribute&lt;DecorationOrderAttribute&gt;();
                  return order?.Order ?? 0;
              }).ToList();
          if (!decorators.Any())
          {
              //If there are no decorators, just registering base service
              builder.RegisterType&lt;TImplementation&gt;()
                  .As&lt;TInterface&gt;()
                  .InstancePerMatchingLifetimeScope(tags);
          }
          else
          {
              builder.RegisterType&lt;TImplementation&gt;()
                  .Named&lt;TInterface&gt;(implType.FullName)
                  .InstancePerMatchingLifetimeScope(tags);
  
              MethodInfo mi = this.GetType().GetMethod(nameof(RegisterDecorator), BindingFlags.NonPublic | BindingFlags.Instance);
  
              //Registering decorators
              for (int i = 0; i &amp;lt; decorators.Count; i++)
              {
                  MethodInfo gmi = mi.MakeGenericMethod(baseType, decorators[i]);
                  gmi.Invoke(this, new object[] {builder, (i == 0) ? implType : decorators[i - 1], decorators[i], tags, i != decorators.Count - 1 });
              }
          }
  
      private void RegisterDecorator&lt;TInterface, TDecorator&gt;(ContainerBuilder builder, Type baseType, Type decoratorType, object[] tags, bool hasKey)
      {
         string decoratorName = decoratorType.FullName;
  
         builder.RegisterType&lt;TDecorator&gt;()
                  .Named&lt;TInterface&gt;(decoratorName)
                  .InstancePerMatchingLifetimeScope(tags);
         builder.RegisterDecorator&lt;TInterface&gt;((c, inner) =&gt; c.ResolveNamed&lt;TInterface&gt;(decoratorName, TypedParameter.From(inner)), baseType.FullName, hasKey ? decoratorName : null)
                  .InstancePerMatchingLifetimeScope(tags);
       }
  }
  }
  </code></pre>
  
  <p>When I make an API-request, I'm getting the following error:
  <br/>
  Circular component dependency detected: MyApp.WebUI.Api.RatingsController -> MyApp.Logic.Services.RatingService -> MyApp.Logic.Handlers.Ratings.RatingHandler[] -> MyApp.Logic.Handlers.Ratings.CommentRatingHandler -> System.Object -> MyApp.Logic.Services.Decorated.WithEventLogging.CommentService -> System.Object.'.
  <br/></p>
  
  <p>I want to achieve the following<br/>
  1. Each service which has decorated service need to be registered as a decorator (for example, CommentService->EventLoggingCommentService->NotificationCommentService, PostService->EventLoggingPostService->NotificationPostService,...)<br/>
  2. Each service which hasn't decorated services need to be registered as self (for example, FavoritesObjectService).</p>
  
  <p>Could you tell me, please, what I'm doing wrong.</p>