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

Applying proxy or Scoped decorators using decorator type factory fails with NullReferenceException on uncontrolled collections. #703

Closed
dotnetjunkie opened this issue May 1, 2019 · 1 comment
Milestone

Comments

@dotnetjunkie
Copy link
Collaborator

Simple Injector blocks the application of both Scoped decorators and proxy decorators to container uncontrolled collections. However, when such decorator registration is made using the overload that takes in a decorator type factory, Simple Injector throws a rather obscure NullReferenceException, instead of throwing the expected descriptive exception.

The following tests reproduce the issue:

sealed class PluginProxy : IPlugin
{
    public PluginProxy(Func<IPlugin> pluginFactory) { }
}

sealed class PluginDecorator : IPlugin
{
    public PluginDecorator(IPlugin plugin) { }
}

[TestMethod]
public void Test1()
{
    // Act
    var container = new Container();

    IEnumerable<IPlugin> collection = new[] { new PluginImpl() };

    container.Collection.Register(containerUncontrolledCollection: collection);
    container.RegisterDecorator(
        typeof(IPlugin),
        _ => typeof(PluginProxy), // factory returning (func-wrapping) proxy
        Lifestyle.Transient,
        _ => true);

    // Act
    Action action = () => container.Verify(); // Currently fails with a NullReferenceException

    // Assert
    AssertThat.ThrowsWithExceptionMessageContains<InvalidOperationException>(
        "It's impossible for the container to generate a Func<IPlugin> for injection into the " +
        "PluginProxy decorator that will be wrapped around instances of the collection of IPlugin " +
        "instances",
        action);
}

[TestMethod]
public void Test2()
{
    // Act
    var container = new Container();
    container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

    IEnumerable<IPlugin> collection = new[] { new PluginImpl() };

    container.Collection.Register(containerUncontrolledCollection: collection);
            
    container.RegisterDecorator(
        typeof(IPlugin),
        _ => typeof(PluginDecorator), // using factory
        Lifestyle.Scoped, // lifestyle other than singleton or transient
        _ => true);

    // Act
    Action action = () => container.Verify(); // Currently fails with a NullReferenceException

    // Assert
    AssertThat.ThrowsWithExceptionMessageContains<InvalidOperationException>(
        "You are trying to apply the PluginDecorator decorator with the 'Async Scoped' lifestyle " +
        "to a collection of type IPlugin, but the registered collection is not controlled by the " +
        "container.",
        action);
}
@dotnetjunkie dotnetjunkie added this to the v4.6 milestone May 1, 2019
@dotnetjunkie
Copy link
Collaborator Author

bug-703 branch created.

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