Home > Software engineering >  Autofac - resolve open generic type to resolve to derived type
Autofac - resolve open generic type to resolve to derived type

Time:06-10

I am trying to use autofac to register open generic type to resolve to derived type

   public interface IBackGroundJobHandler<T>  where T: INotification
 {
    public Task Handle(T notification, CancellationToken cancellationToken);
   
 }

 public  abstract class EventHandler<T> : IBackGroundJobHandler<T> where T : INotification
{
    public abstract Task Handle(T notification, CancellationToken cancellationToken);
}



 public class TestEventHandler : EventHandler<TestEvent>
{
    public async override Task Handle(TestEvent notification, CancellationToken 
     cancellationToken)
    {
        await Task.Delay(20000);
        System.Diagnostics.Debug.WriteLine("Test Event Finished");

    }
}

 public class SomeService<T> where T:INotfication
{
   public SomeService(IBackGroundJobHandler<T> handler)
  {
       //sometask
  }
 }

 

I tried registering it by :

        builder.RegisterGeneric(typeof(EventHandler<>)).As(typeof(IBackGroundJobHandler<>))
        .InstancePerLifetimeScope();

IBackgroundJobHandler is not resolving in service constructor.

I also tried:

 builder.RegisterAssemblyTypes(typeof(EventHandler).GetTypeInfo().Assembly)    
.AsClosedTypesOf(typeof(IBackGroundJobHandler<>)).InstancePerLifetimeScope();

I am new to autofac, how can I resolve this?

CodePudding user response:

I avoided abstract class and simply used generic interface IBackGroundJobHandler<>

public class TestEventHandler : IBackGroundJobHandler<TestEvent>
{
   public async override Task Handle(TestEvent notification, CancellationToken 
   cancellationToken)
 {
    //Task

 }
}

Registered in Autofac container as:

builder.RegisterAssemblyTypes(typeof(IBackGroundEventHandler<>)
.GetTypeInfo().Assembly)                
.AsClosedTypesOf(typeof(IBackGroundEventHandler<>))
.InstancePerLifetimeScope()
.AsImplementedInterfaces();

CodePudding user response:

EventHandler<T> is an abstract class, so the Autofac resolver will not be able to create one anyway.

You've not registered TestEventHandler (for example), so Autofac is unaware of it.

When you request a IBackGroundJobHandler<TestEvent>, I presume that you want to get a TestEventHandler resolved, but that class has not been registered.

So, given that you need to register TestEventHandler, you probably don't need that EventHandler<T> abstract class anyway. (I'm guessing that you thought that would be a way of registering all classes that derived from EventHandler<T> in on go). The TestEventHandler can just implement IBackGroundJobHandler<TestEvent>.

class TestEventHandler : IBackGroundJobHandler<TestEvent>
{
    public async Task Handle(TestEvent notification, CancellationToken cancellationToken)
    {
         // Process the Test Event
    }
}

Then use:

builder.RegisterType<TestEventHandler>()
    .As<IBackGroundJobHandler<TestEvent>>()
    .InstancePerLifetimeScope();

If you have many event handlers, it can be a pain, so I'd use reflection to find the classes that do implement the interface:

// Get the assembly that contains the implementors, assuming
// they are all in the same assembly as the TestEventHandler:
Assembly assembly = typeof(TestEventHandler).Assembly;

// Get all classes from assembly that implement the required interface
Type[] classesThatImplementIBackGroundJobHandler = assembly.GetTypes()
   .Where(t => t.IsClass 
       && t.GetInterfaces().Any(i => 
           i.IsGenericType 
           && i.GetGenericTypeDefinition() == typeof(IBackGroundJobHandler<>).GetGenericTypeDefinition())).ToArray();

// Register All Types that Implement our interface
builder.RegisterTypes(classesThatImplementIBackGrounJobHandler)
    .AsImplementedInterfaces()
    .InstancePerLifetimeScope();
      
    .
  • Related