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

Which NServiceBus integration package for Simple Injector to use? #725

Open
MyPierre opened this issue Jun 11, 2019 · 8 comments

Comments

Projects
None yet
4 participants
@MyPierre
Copy link

commented Jun 11, 2019

Hi,
I will have to use NServiceBus for a project. I haven't found many resources to implement it with SimpleInjector. But I saw that there is a package called NServiceBus.SimpleInjector (NServiceBus.SimpleInjector).
https://github.com/dotnetjunkie/NServiceBus.SimpleInjector.
It would help me if someone could explain how we configure Simpleinjector to use it and the usage of it ?
Thank you for your help.

@MyPierre MyPierre added the question label Jun 11, 2019

@dotnetjunkie

This comment has been minimized.

Copy link
Collaborator

commented Jun 11, 2019

That package wasn't made by me or other contributors. You will have to go to the creator of the package to find out how to use that package.

Note the following:

  • The NServiceBus.SimpleInjector NuGet package is created by @WilliamBZA
  • The NServiceBus.SimpleInjector NuGet package is not an official Simple Injector package. We don't know how it works and can't support it.
  • The NServiceBus.SimpleInjector NuGet package is not an official NServiceBus package. They mention it on their website, but they state that it "is a community maintained project."
  • The NServiceBus.SimpleInjector NuGet package is unrelated to my https://github.com/dotnetjunkie/NServiceBus.SimpleInjector repository. That repo is a fork from @kijanawoodard's proof of concept. This POC was never finished.

Summary, you are mentioning two things that are not related in any way.

@dotnetjunkie

This comment has been minimized.

Copy link
Collaborator

commented Jun 11, 2019

I would advise against using that NServiceBus.SimpleInjector package, because it implicitly changes a lot of the inner workings of Simple Injector and because the expectations of NServiceBus-made registrations differs from how Simple Injector behaves.

Instead, you should keep NServiceBus's default container in, and let it resolve all its framework-made registrations, while intercepting the creation of application-specific components. These application-specific components are typically just the message handlers (with their dependencies).

A few years back (2016) I created such interceptor implementation in a mail discussion with @kijanawoodard that uses this. This is the code:

using SimpleInjector;
using SimpleInjector.Lifestyles;

public sealed class SimpleInjectorBuilder : IContainer
{
    private readonly Container container;
    private readonly IContainer nsbContainer;
 
    private SimpleInjectorBuilder(Container appContainer, IContainer nsbContainer)
    {
        this.container = appContainer;
        this.nsbContainer = nsbContainer;
    }

    // Declare which root types must be resolved by Simple Injector—typically only
    // the message handlers.
    private bool IsApplicationType(Type typeToBuild) =>
        typeToBuild.IsGenericType
        && typeToBuild.GetGenericTypeDefinition() == typeof(IHandleMessages<>);
 
    public object Build(Type typeToBuild) =>
        IsApplicationType(typeToBuild)
            ? this.container.GetInstance(typeToBuild)
            : this.nsbContainer.Build(typeToBuild);
 
    public IEnumerable<object> BuildAll(Type typeToBuild) =>
        IsApplicationType(typeToBuild)
            ? this.container.GetAllInstances(typeToBuild)
            : this.nsbContainer.BuildAll(typeToBuild);
 
    public IContainer BuildChildContainer() => 
        new SimpleInjectorScope(this, AsyncScopedLifestyle.BeginScope(this.container));
 
    public void Dispose() { }
    
    private sealed class SimpleInjectorScope : IContainer
    {
        private readonly SimpleInjectorBuilder builder;
        private readonly SimpleInjector.Scope scope;
        
        public SimpleInjectorScope(SimpleInjectorBuilder builder, SimpleInjector.Scope scope)
        {
            this.builder = builder;
            this.scope = scope;
        }
                
        public object Build(Type typeToBuild) => this.builder.Build(typeToBuild);
        public IEnumerable<object> BuildAll(Type typeToBuild) =>this.builder.BuildAll(typeToBuild);
        public void Release(object instance) { }
        public void Dispose() => this.scope.Dispose();
    }
}
var container = new SimpleInjector.Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

// Register application types, such as your message handlers:
var handlerAssemblies = AppDomain.CurrentDomain.GetAssemblies();
container.Register(typeof(IHandleMessages<>), handlerAssemblies);

// Use Simple Injector to resolve application types in NServiceBus:
busConfiguration.UseContainer(
    new SimpleInjectorBuilder(
        appContainer: container, // use Simple Injector for application stuff
        nsbContainer: new AutofacObjectBuilder())); // Keep using Autofac for framework stuff

Do note that this code still uses Autofac, while I believe that the newest NServiceBus version uses a different container.

@DanielLebon

This comment has been minimized.

Copy link

commented Jun 11, 2019

Thank you dotnetjunkie for sharing this very technical implementation and not at all obvious to find.

@MyPierre

This comment has been minimized.

Copy link
Author

commented Jun 11, 2019

Thank you for your great help.
It s an interesting solution, i am going to try it

@Gachapen

This comment has been minimized.

Copy link

commented Jun 12, 2019

I'm a little bit confused. @dotnetjunkie, are you referring to the package on nuget, which is also documented by Particular, i.e. https://www.nuget.org/packages/NServiceBus.SimpleInjector/ made by WilliamBZA? Because @MyPierre linked to one of your repositories: https://github.com/dotnetjunkie/NServiceBus.SimpleInjector

And if you advice against using that package, maybe we should bring this up with Particular?
Particular documentation: https://docs.particular.net/nservicebus/dependency-injection/simpleinjector

@dotnetjunkie

This comment has been minimized.

Copy link
Collaborator

commented Jun 12, 2019

I was referring to WilliamBZA's package, and wasn't aware I still had a cloned repository lying around. Thay repo was just a POC and is not working code. I advise the use of the code I provided above, as it is much more stable and won't push you down the Conforming Container rabbit hole.

@MyPierre

This comment has been minimized.

Copy link
Author

commented Jun 12, 2019

Hi dotnetjunkie ,
Following your remark : "I believe that the newest NServiceBus version uses a different container.",
I asked Nservivcebus team for information and indeed the container used is:
LightInject:
https://github.com/Particular/NServiceBus/blob/develop/src/NServiceBus.Core/NServiceBus.Core.csproj#L23

Do you see a possible adaptation way of your code for this container ?

Thank you for your help.

@dotnetjunkie

This comment has been minimized.

Copy link
Collaborator

commented Jun 12, 2019

Do you see a possible adaptation way of your code for this container ?

Probably just change the following code:

// Use Simple Injector to resolve application types in NServiceBus:
busConfiguration.UseContainer(
    new SimpleInjectorBuilder(
        appContainer: container, // use Simple Injector for application stuff
        nsbContainer: new LightInjectObjectBuilder())); // Keep using Autofac for framework stuff

@dotnetjunkie dotnetjunkie changed the title Simple injector and NserviceBus (NServiceBus.SimpleInjector dotnetjunke package) Which NServiceBus integration package for Simple Injector to use? Jun 17, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.