Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify extending injection behavior #707

Open
dotnetjunkie opened this issue May 7, 2019 · 1 comment
Open

Simplify extending injection behavior #707

dotnetjunkie opened this issue May 7, 2019 · 1 comment

Comments

@dotnetjunkie
Copy link
Collaborator

dotnetjunkie commented May 7, 2019

Simple Injector allows its dependency injection behavior to be altered by the use of the IDependencyInjectionBehavior interface, e.g.:

var container = new Container();
container.Options.DependencyInjectionBehavior = new CustomBehavior(container);

This approach, however, contains the following downsides:

  • Because the dependency injection behavior consists of argument verification, which gets triggered for every made registration, this behavior needs to be set very early in the pipeline, before any registrations are made.
  • The creation of a new implementation is cumbersome, for the default use case.

The default use case for adding a new behavior is the following:

  • Only the GetInstanceProducer needs to be implemented, where the Verify just forwards to the wrapped (or original) IDependencyInjectionBehavior implementation.
  • The new behavior almost never completely replaces the original behavior, but rather is an append model, where the behavior returns InstanceProducer instances for a sub set of dependencies.

I'm currently looking at simplifying integration with .NET Core and making it easier to integrate Microsoft's ILogger into Simple Injector (much as described here). Integration with ILogger, however, means the creation of a custom IDependencyInjectionBehavior, for instance using a custom AddLogging() extension method. The order in which a user calls AddLogging(), unfortunately, is not very undeterministic. Although we could throw a descriptive exception explaining the user to call AddLogging sooner, this still might cause problems as registrations might have been added already to the container, rendering the AddLogging extension useless.

With respect to this use case, I like to allow "verification-less injection behaviors" to be added to the container even after registrations are made, up to the point that the container is locked.

I, therefore, suggest the addition of a helper method on ContainerOptions that simplifies this use case, and allows the previous downsides to be fixed:

// Method on ContainerOptions
// Calling this method multiple times works as a decorator. When the delegate returns null
// the previously added delegate will be called.
public void AddDependencyInjectionBehavior(
    Func<InjectionConsumerInfo, InstanceProducer?> extension);

With the following usage:

var container = new Container();
container.Register<ISomething, IImpl>();

container.Options.AddDependencyInjectionBehavior(info =>
    i.Target.TargetType == typeof(ILogger)
        ? Lifestyle.Singleton.CreateProducer(() => factory.CreateLogger(type), container)
        : null);

container.GetInstance<ISomething>();

Open questions:

  • When AddDependencyInjectionBehavior is called multiple times with new IDependencyInjectionBehavior implementations being hooked as well, in which order should they be executed? (e.g. should each call to AddDependencyInjectionBehavior result in a new IDependencyInjectionBehavior implementation replacing the original one?)
  • Should the addition of a full IDependencyInjectionBehavior implementation (i.e. calling Options.DependencyInjectionBehavior) be able to replace all AddDependencyInjectionBehavior delegates by not calling the wrapped implementation?
@dotnetjunkie
Copy link
Collaborator Author

After some more thought, and consulting with @TheBigRic, I have to conclude that:

  1. This feature needs more thought—the open questions are not easily answered.
  2. The described ILogger use case can be implemented with a conditional logger implementation as well, making this feature less urgent to add.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant