Is it possible to set/change the dependency lifetime scoping options (Transient, Single, PerWebReqest, etc...) for one, two or x number of specific assemblies if you're auto registering/discovering your dependencies? I have sample code below:
public class RegistrationPackage : IPackage
{
public void RegisterServices(Container container)
{
var @namespace = "ConsoleLib";
var assemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => a.FullName.StartsWith(@namespace))
.Select(a => a).ToList();
var names = assemblies.Select(a => a.FullName);
Action<string> poormanslogger = Console.WriteLine;
//poormanslogger = Trace.WriteLine;
foreach (var name in names)
poormanslogger("Located the following assemblies: " + name);
// could combine these two and remove the if statement for the open generic registrations below
//container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>), AppDomain.CurrentDomain.GetAssemblies());
foreach (var assembly in assemblies)
foreach (var type in assembly.GetExportedTypes().Where(a => !a.IsAbstract))
{
poormanslogger(string.Format("Exported Type: {0}", type.Name));
foreach (var @interface in type.GetInterfaces())
{
poormanslogger(string.Format("\tInterface type: {0}", @interface.Name));
// register open generic
if (@interface.IsGenericType && !type.IsAbstract && type.IsGenericType)
container.RegisterManyForOpenGeneric(type, assemblies);
// register closed generic
if (@interface.IsGenericType && !type.IsAbstract && !type.IsGenericType)
container.Register(@interface, type, Lifestyle.Transient);
// register non generic
if (!type.IsGenericType && !@interface.IsGenericType && !type.IsAbstract)
container.Register(@interface, type, Lifestyle.Transient);
}
// unregistered type fall back...
//container.RegisterOpenGeneric(typeof(ICommandHandler<>), typeof(UnRegisteredCommandHandler<>));
}
// The decorators are applied in the order in which they are registered
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(DeadlockRetryCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(ValidationCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(SecurityCommandHandlerDecorator<>));
}
}
Then I have the standard stuff:
var container = new Container();
container.RegisterPackages();
container.Verify();
var instance = container.GetInstance<ICommandHandler<UnregisteredCommand>>();
instance.Handle(new UnregisteredCommand());
Could I possibly use the ExpressionBuilding event?
The batch-registration facilities that Simple Injector offers limits itself to registration of generic types. The documentation explains why:
But even for batch-registrations for types of a generic interface there's no built-in support to differentiate between lifestyles. This is quite deliberate, since this would force you to place library defined attributes on your classes to describe the lifestyle, and this would make your application dependent on Simple Injector, which is something we want to prevent.
Simple Injector 2.6 introduces a new extension point called the lifestyle selection behavior. This extension point allows you to override the default selection behavior of the framework when no lifestyle is supplied explicitly. The default behavior is to use
Lifestyle.Transient
.If you need something like this, you should override the default lifestyle selection behavior and create an attribute that you can apply to your components. That could look something like this:
This attribute should be defined in a base project of your application so each class can be marked with it:
Using this defined attribute, we can now define our custom lifestyle selection behavior as follows:
This custom behavior can be registered as follows:
With this in place we simplified the batch registration, and we don't have to do anything special to select the proper lifestyle:
Instead of overriding the lifestyle selection behavior, another option is to have everything register as transient (since that would be a sensible default), but override those few registrations that should be registered otherwise: