简体   繁体   中英

How to register multiple classes that implements the same interface to UnityContainer?

I am trying to setup IoC container in my Asp.Net MVC 5 application so I can access these objects anywhere in my application.

I choose to use Unity.Mvc container for the job.

I want to use reflection or some other technique to auto register any class in my assemblies that implements an interface called IRunOnEachRequest .

Here is what I did

I created the following interfaces

public interface IRunTask
{
    void Run();
}

public interface IRunAfterEachRequest : IRunTask
{
}

public interface IRunOnEachRequest : IRunTask
{
}

Then in the UnityConfig.RegisterTypes method, I am trying to do the following

var assemnlies = AppDomain.CurrentDomain.GetAssemblies().ToList();

foreach (Assembly assembly in assemnlies)
{
    try
    {
        var tasks = assembly.GetTypes().Where(x => x.IsClass && typeof(IRunTask).IsAssignableFrom(x)).ToList();

        foreach (Type task in tasks)
        {

            if (typeof(IRunAfterEachRequest).IsAssignableFrom(task))
            {
                //container.RegisterType<IRunAfterEachRequest, typeof(task)>();
            }
            else if (typeof(IRunOnEachRequest).IsAssignableFrom(task))
            {
                //container.RegisterType<IRunOnEachRequest, typeof(task)>();
            }
        }
    }
    catch
    {

    }
}

But the line container.RegisterType<IRunAfterEachRequest, typeof(task)>(); is giving me error.

Questions

  • Is there a better more elegant want into registering multiple types in UnityContainer?
  • Is there a way to auto register using a default convention? For Example, if I have an interface called IUnitOfWork and implementation called UnitOfWork in current assembly "same name without the I then register them into the container automatically.

The trick is to register them by name:

public interface IRunTask
{
    void Run();
}

public class RunTask1 : IRunTask { public void Run() { } }
public class RunTask2 : IRunTask { public void Run() { } }
public class RunTask3 : IRunTask { public void Run() { } }

Execution code:

var ctr = new UnityContainer();
var taskTypes = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsClass && typeof(IRunTask).IsAssignableFrom(x)).ToList();

// Register from IRunTask to T using T.Name as a unique key for the name. You can add additional params like a lifetimemanager etc.
taskTypes.ForEach(t => ctr.RegisterType(typeof(IRunTask), t, t.Name));
var tasks = ctr.ResolveAll<IRunTask>().ToList(); // RT1, RT2, RT3
tasks.ForEach(t => t.Run());

Is there a better more elegant want into registering multiple types in UnityContainer?

I prefer to register via a config file and I never used Unity for Resolving multiple types that have the same interface (I've done this in the past using MEF which I have no idea if it's still popular for resolving plugins).

Is there a way to auto register using a default convention? For Example, if I have an interface called IUnitOfWork and implementation called UnitOfWork in current assembly "same name without the I then register them into the container automatically.

I'm not sure, but I think you are missing something here. The whole purpose of IOC is to create more than one type (could be a mock for a unit test, a behavior or a multi-tenant plugin). I wouldn't want my app to auto register types.
If you still insist, you can create a default attribute and simply write some reflection code that will auto register types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM