What you’re looking for is the concept of Auto-Registration. Most containers allow you to either register types in an assembly based on a convention, or do unregistered type resolution and find the missing type for you.
For instance, you can search through an assembly and register all types that match the convention during startup:
var container = new Container();
Assembly assembly = typeof(Thing).Assembly;
var mappings =
from type in assembly.GetExportedTypes()
let matchingInterface = "I" + type.Name
let service = type.GetInterfaces().FirstOrDefault(i => matchingInterface)
where service != null
select new { service, type };
foreach (var mapping in mappings)
{
// Register the type in the container
container.Register(mapping.service, mapping.type);
}
Using unregistered type resolution, you can make the registration on the fly. How to do this is very much dependent on which container you use. With Simple Injector, for instance, this looks as follows:
var container = new Container();
Assembly assembly = typeof(Thing).Assembly;
container.ResolveUnregisteredType += (s, e)
{
Type service = e.UnregisteredServiceType;
if (service.IsInterface)
{
var types = (
from type in asssembly.GetExportedTypes()
where service.IsAssignableFrom(type)
where !type.IsAbstract
where service.Name == "I" + type.Name
select type)
.ToArray();
if (types.Length == 1)
{
e.Register(Lifestyle.Transient.CreateRegistration(types[0], container));
}
}
};
Both methods prevent you from having to update your container configuration constantly.
7
solved IoC container that doesn’t require registration