├── .github
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── AdditionalHandlerAssembly
├── AdditionalHandlerAssembly.csproj
└── ControllerChangeMessageHandler.cs
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── MessageHandlers
├── EventAggregator.cs
├── FirstHandler.cs
├── MessageHandlers.csproj
└── SecondHandler.cs
├── README.md
├── Rebus.Autofac.Tests
├── AutofacActivationContext.cs
├── AutofacContainerTests.cs
├── AutofacRealContainerTests.cs
├── Bugs
│ ├── CanGetMessageHandlerWhenDoingSecondLevelRetries.cs
│ ├── DoesNotTryToHandleMessagesBeforeTheBusIsProperlyStarted.cs
│ ├── RegistersHandlerAsImplementationOfIFailedForDerivedMessagesToo.cs
│ ├── RegistersHandlerAsImplementationOfIFailedToo.cs
│ └── ReproduceDoubleDispatchIssue.cs
├── CheckNewApi.cs
├── CheckResolutionPerformance.cs
├── Rebus.Autofac.Tests.csproj
├── TestAutofacAssumptions.cs
└── TestRegistrationApi.cs
├── Rebus.Autofac.sln
├── Rebus.Autofac
├── Autofac
│ └── AutofacHandlerActivator.cs
├── Config
│ ├── ContainerBuilderExtensions.cs
│ └── ContainerExtensions.cs
├── Internals
│ ├── InternalsVisibleTo.cs
│ └── TypeExtensions.cs
└── Rebus.Autofac.csproj
├── appveyor.yml
├── artwork
└── little_rebusbus2_copy-500x500.png
├── scripts
├── build.cmd
├── push.cmd
└── release.cmd
└── tools
└── NuGet
└── nuget.exe
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ---
2 | Rebus is [MIT-licensed](https://opensource.org/licenses/MIT). The code submitted in this pull request needs to carry the MIT license too. By leaving this text in, __I hereby acknowledge that the code submitted in the pull request has the MIT license and can be merged with the Rebus codebase__.
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | obj
2 | bin
3 | deploy
4 | deploy/*
5 | _ReSharper.*
6 | *.csproj.user
7 | *.resharper.user
8 | *.ReSharper.user
9 | *.teamcity.user
10 | *.TeamCity.user
11 | *.resharper
12 | *.DotSettings.user
13 | *.dotsettings.user
14 | *.ncrunchproject
15 | *.ncrunchsolution
16 | *.suo
17 | *.cache
18 | ~$*
19 | .vs
20 | .vs/*
21 | _NCrunch_*
22 | *.user
23 | *.backup
24 |
25 | # MS Guideline
26 | **/packages/*
27 | !**/packages/build/
28 | AssemblyInfo_Patch.cs
29 | /.idea/
30 |
--------------------------------------------------------------------------------
/AdditionalHandlerAssembly/AdditionalHandlerAssembly.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AdditionalHandlerAssembly/ControllerChangeMessageHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Threading.Tasks;
4 | using Rebus.Handlers;
5 | #pragma warning disable 1998
6 |
7 | namespace AdditionalHandlerAssembly
8 | {
9 | public class ControllerChangeMessageHandler : IHandleMessages
10 | {
11 | readonly ConcurrentQueue _handledMessages;
12 |
13 | public ControllerChangeMessageHandler(ConcurrentQueue handledMessages) => _handledMessages = handledMessages ?? throw new ArgumentNullException(nameof(handledMessages));
14 |
15 | public async Task Handle(ControllerChangeMessage message) => _handledMessages.Enqueue(message);
16 | }
17 |
18 | public class ControllerChangeMessage { }
19 | }
20 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 2.0.0-a1
4 | * Update Autofac dependency to 4.1.0
5 |
6 | ## 2.0.0-a2
7 | * Test build
8 |
9 | ## 2.0.0-b01
10 | * Test release
11 |
12 | ## 2.0.0
13 | * Release 2.0.0
14 |
15 | ## 3.0.0
16 | * Update to Rebus 3
17 |
18 | ## 4.0.0
19 | * Update to Rebus 4
20 | * Add .NET Core support (netstandard1.6)
21 | * Fix csproj - thanks [robvanpamel]
22 | * Update Autofac dep to 4.5.0
23 | * Update contracts dep - thanks [trevorreeves]
24 |
25 | ## 5.0.0
26 | * Change API to work better with the Autofac container builder - no more `.Update` :)
27 |
28 | ## 5.1.0
29 | * Additional `RegisterRebus` overload that passes `IComponentContext` to the configuration method
30 |
31 | ## 5.2.0
32 | * Add Rebus handler registration extensions on `ContainerBuilder` and improve resolution performance
33 |
34 | ## 6.0.0
35 | * Move polymorphic handler resolution resposiblity to the container. If contravariant lookup is wanted, one must register `ContravariantRegistrationSource` on the `ContainerBuilder`
36 | * Update to Rebus 5 and Autofac 5
37 | * Fix dispatch of `IFailed` when 2nd level retry is enabled - thanks [oliverhanappi]
38 | * Fix subtle issues and make implementation that fixes dispatch of `IFailed` more elegant - thanks [oliverhanappi]
39 | * Registration helpers should only register handlers under their implemented handler interfaces
40 | * Fix resolution-during-startup race condition bug - thanks [leomenca]
41 | * Fix bug that would erronously dispatch 2nd level retries twice
42 |
43 | ## 7.0.0
44 | * Update to Rebus 6
45 |
46 | ## 7.1.0
47 | * Remove CLS compliance attribute accidentally left over from the past
48 |
49 | ## 7.2.0
50 | * Additional registration overloads - thanks [kendallb]
51 |
52 | ## 7.3.0
53 | * Move multiple registrations check to the builder's registration callback, because it doesn't interfere with the container's `IBus` registration. This way, `IBus` can be overridden/decorated if desired. The check can also be disabled alltogether by passing `disableMultipleRegistrationsCheck: true` to the `RegisterRebus` method.
54 |
55 | ## 8.0.0
56 | * Rename `startBus` to `startAutomatically` to be consistent with other modern containers
57 | * Add container extension method `container.StartBus()` to make starting the bus more convenient
58 |
59 | ## 9.0.0
60 | * Update to Rebus 8
61 | * Update to Autofac 7.1.0
62 |
63 | [kendallb]: https://github.com/kendallb
64 | [leomenca]: https://github.com/leomenca
65 | [oliverhanappi]: https://github.com/oliverhanappi
66 | [robvanpamel]: https://github.com/robvanpamel
67 | [trevorreeves]: https://github.com/trevorreeves
68 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributions are most welcome! :)
2 |
3 | I do prefer it if we communicate a little bit before you send PRs, though.
4 | This is because _I value your time_, and it would be a shame if you spent time
5 | working on something that could be made better in another way, or wasn't
6 | actually needed because what you wanted to achieve could be done better in
7 | another way, etc.
8 |
9 | ## "Beginners"
10 |
11 | Contributions are ALSO very welcome if you consider yourself a beginner
12 | at open source. Everyone has to start somewhere, right?
13 |
14 | Here's how you would ideally do it if you were to contribute to Rebus:
15 |
16 | * Pick an [issue](https://github.com/rebus-org/Rebus/issues) you're interested in doing,
17 | or dream up something yourself that you feel is missing.
18 | * If you talk to me first (either via comments on the issue or by email), I
19 | will guarantee that your contribution is accepted.
20 | * Send me a "pull request" (which is how you make contributions on GitHub)
21 |
22 | ### Here's how you create a pull request/PR
23 |
24 | * Fork Rebus ([Fork A Repo @ GitHub docs](https://help.github.com/articles/fork-a-repo/))
25 | * Clone your fork ([Cloning A Repository @ GitHub docs](https://help.github.com/articles/cloning-a-repository/))
26 | * Make changes to your local copy (e.g. `git commit -am"bam!!!11"` - check [this](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository) out for more info)
27 | * Push your local changes to your fork ([Pushing To A Remote @ GitHub docs](https://help.github.com/articles/pushing-to-a-remote/))
28 | * Send me a pull request ([Using Pull Requests @ GitHub docs](https://help.github.com/articles/using-pull-requests/))
29 |
30 | When you do this, your changes become visible to me. I can then review it, and we can discuss
31 | each line of code if necessary.
32 |
33 | If you push additional changes to your fork during this process,
34 | the changes become immediately available in the pull request.
35 |
36 | When all is good, I accept your PR by merging it, and then you're (even more) awesome!
37 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Rebus is licensed under [The MIT License (MIT)](http://opensource.org/licenses/MIT)
2 |
3 | # The MIT License (MIT)
4 |
5 | Copyright (c) 2012-2016 Mogens Heller Grabe
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | THE SOFTWARE.
24 |
25 | -------
26 |
27 | This license was chosen with the intention of making it easy for everyone to use Rebus. If the license has the opposite effect for your specific usage/organization/whatever, please contact me and we'll see if we can work something out.
--------------------------------------------------------------------------------
/MessageHandlers/EventAggregator.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace MessageHandlers
7 | {
8 | public class EventAggregator : IEnumerable
9 | {
10 | readonly ConcurrentQueue _events = new ConcurrentQueue();
11 |
12 | public void Register(string e) => _events.Enqueue(e);
13 |
14 | public IEnumerator GetEnumerator() => _events.ToList().GetEnumerator();
15 |
16 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MessageHandlers/FirstHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using Rebus.Handlers;
3 | #pragma warning disable 1998
4 |
5 | namespace MessageHandlers
6 | {
7 | public class FirstHandler : IHandleMessages
8 | {
9 | readonly EventAggregator _eventAggregator;
10 |
11 | public FirstHandler(EventAggregator eventAggregator) => _eventAggregator = eventAggregator;
12 |
13 | public async Task Handle(string message) => _eventAggregator.Register($"FirstHandler handling {message}");
14 | }
15 | }
--------------------------------------------------------------------------------
/MessageHandlers/MessageHandlers.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MessageHandlers/SecondHandler.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using Rebus.Handlers;
3 | #pragma warning disable 1998
4 |
5 | namespace MessageHandlers
6 | {
7 | public class SecondHandler : IHandleMessages
8 | {
9 | readonly EventAggregator _eventAggregator;
10 |
11 | public SecondHandler(EventAggregator eventAggregator) => _eventAggregator = eventAggregator;
12 |
13 | public async Task Handle(string message) => _eventAggregator.Register($"SecondHandler handling {message}");
14 | }
15 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Rebus.Autofac
2 |
3 | [](https://www.nuget.org/packages/Rebus.Autofac)
4 |
5 | Provides an Autofac container adapter for [Rebus](https://github.com/rebus-org/Rebus).
6 |
7 | 
8 |
9 | ---
10 |
11 | Use the Autofac container adapter like this:
12 |
13 | ```csharp
14 | var builder = new ContainerBuilder();
15 |
16 | builder.RegisterRebus((configurer, context) => configurer
17 | .Logging(l => l.Serilog())
18 | .Transport(t => t.UseRabbitMq(...))
19 | .Options(o => {
20 | o.SetNumberOfWorkers(2);
21 | o.SetMaxParallelism(30);
22 | }));
23 |
24 | // the bus is registered now, but it has not been started.... make all your other registrations, and then:
25 | var container = builder.Build(); //< start the bus
26 |
27 |
28 | // now your application is running
29 |
30 |
31 | // ALWAYS do this when your application shuts down:
32 | container.Dispose();
33 | ```
34 |
35 | It will automatically register the following services in Autofac:
36 |
37 | * `IBus` – this is the bus singleton
38 | * `IBusStarter` – this is the bus starter you can use to start it manually
39 | * `IMessageContext` – this is the current message context – can be injected into Rebus message handlers and everything resolved at the time of receiving a new message
40 | * `ISyncBus` – this is the synchronous bus instance – can be used in places, where a `Task`-based asynchronous API is not desired, e.g. from deep within ASP.NET or WPF applications, which would deadlock if you went `.Wait()` on a `Task`
41 |
42 | Not that if you wish to regiser the bus and not start it automatically, you can stil register the number of workers but have it not start anything until you are ready for the bus to be started. This is usefu if you wish to separate the processing of messages from the sending of messages (separate tasks, services etc). You would do it like this:
43 |
44 | ```csharp
45 | var builder = new ContainerBuilder();
46 |
47 | builder.RegisterRebus((configurer, context) => configurer
48 | .Logging(l => l.Serilog())
49 | .Transport(t => t.UseRabbitMq(...))
50 | .Options(o => {
51 | o.SetNumberOfWorkers(2);
52 | o.SetMaxParallelism(30);
53 | }),
54 | false); // <--- here we tell it not to start the bus
55 |
56 | // the bus is registered now, but it has not been started.... make all your other registrations, and then:
57 | var container = builder.Build();
58 | var busStarter = container.Resolve();
59 | busStarter.Start(); //< start the bus
60 |
61 |
62 | // now your application is running
63 |
64 |
65 | // ALWAYS do this when your application shuts down:
66 | container.Dispose();
67 | ```
68 |
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/AutofacActivationContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Autofac;
5 | using Rebus.Activation;
6 | using Rebus.Bus;
7 | using Rebus.Config;
8 | using Rebus.Handlers;
9 | using Rebus.Tests.Contracts.Activation;
10 | // ReSharper disable ArgumentsStyleLiteral
11 |
12 | namespace Rebus.Autofac.Tests;
13 |
14 | public class AutofacActivationContext : IActivationContext
15 | {
16 | public IHandlerActivator CreateActivator(Action configureHandlers, out IActivatedContainer container)
17 | {
18 | var builder = new ContainerBuilder();
19 | configureHandlers(new HandlerRegistry(builder));
20 |
21 | var containerAdapter = new AutofacHandlerActivator(builder, (conf, con) => { }, startBus: false, enablePolymorphicDispatch: true, multipleRegistrationsCheckEnabled: true);
22 |
23 | var autofacContainer = builder.Build();
24 | container = new ActivatedContainer(autofacContainer);
25 |
26 | return containerAdapter;
27 | }
28 |
29 | public IBus CreateBus(Action configureHandlers, Func configureBus, out IActivatedContainer container)
30 | {
31 | var containerBuilder = new ContainerBuilder();
32 | configureHandlers(new HandlerRegistry(containerBuilder));
33 |
34 | new AutofacHandlerActivator(containerBuilder, (conf, con) => configureBus(conf), startBus: true, enablePolymorphicDispatch: true, multipleRegistrationsCheckEnabled: true);
35 |
36 | var autofacContainer = containerBuilder.Build();
37 | container = new ActivatedContainer(autofacContainer);
38 |
39 | return container.ResolveBus();
40 | }
41 |
42 | class HandlerRegistry : IHandlerRegistry
43 | {
44 | readonly ContainerBuilder _containerBuilder;
45 |
46 | public HandlerRegistry(ContainerBuilder containerBuilder)
47 | {
48 | _containerBuilder = containerBuilder;
49 | }
50 |
51 | public IHandlerRegistry Register() where THandler : class, IHandleMessages
52 | {
53 | _containerBuilder.RegisterType()
54 | .As(GetHandlerInterfaces().ToArray())
55 | .InstancePerDependency();
56 |
57 | return this;
58 | }
59 |
60 | static IEnumerable GetHandlerInterfaces() where THandler : class, IHandleMessages
61 | {
62 | return typeof(THandler)
63 | .GetInterfaces()
64 | .Where(i => HasGenericTypeDefinition(i, typeof(IHandleMessages<>)));
65 | }
66 |
67 | static bool HasGenericTypeDefinition(Type type, Type openGenericType)
68 | {
69 | return type.IsGenericType && type.GetGenericTypeDefinition() == openGenericType;
70 | }
71 | }
72 |
73 | class ActivatedContainer : IActivatedContainer
74 | {
75 | readonly IContainer _container;
76 |
77 | public ActivatedContainer(IContainer container)
78 | {
79 | _container = container;
80 | }
81 |
82 | public void Dispose()
83 | {
84 | _container.Dispose();
85 | }
86 |
87 | public IBus ResolveBus()
88 | {
89 | return _container.Resolve();
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/AutofacContainerTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Rebus.Tests.Contracts.Activation;
3 |
4 | namespace Rebus.Autofac.Tests;
5 |
6 | [TestFixture]
7 | public class AutofacContainerTests : ContainerTests
8 | {
9 | }
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/AutofacRealContainerTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using Rebus.Tests.Contracts.Activation;
3 |
4 | namespace Rebus.Autofac.Tests;
5 |
6 | [TestFixture]
7 | public class AutofacRealContainerTests : RealContainerTests
8 | {
9 | }
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/Bugs/CanGetMessageHandlerWhenDoingSecondLevelRetries.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Threading.Tasks;
4 | using Autofac;
5 | using NUnit.Framework;
6 | using Rebus.Bus;
7 | using Rebus.Config;
8 | using Rebus.Handlers;
9 | using Rebus.Retry.Simple;
10 | using Rebus.Tests.Contracts.Extensions;
11 | using Rebus.Transport.InMem;
12 | #pragma warning disable 1998
13 |
14 | namespace Rebus.Autofac.Tests.Bugs;
15 |
16 | [TestFixture]
17 | public class CanGetMessageHandlerWhenDoingSecondLevelRetries
18 | {
19 | [Test]
20 | public async Task ItWorks()
21 | {
22 | var network = new InMemNetwork();
23 | var builder = new ContainerBuilder();
24 | var stuff = new ConcurrentQueue();
25 |
26 | builder.RegisterInstance(stuff);
27 |
28 | builder.RegisterRebus(configure =>
29 | configure
30 | .Logging(l => l.None())
31 | .Transport(t => t.UseInMemoryTransport(network, "test"))
32 | .Options(o => o.RetryStrategy(secondLevelRetriesEnabled: true, maxDeliveryAttempts: 1))
33 | );
34 |
35 | builder.RegisterHandler();
36 |
37 | await using var container = builder.Build();
38 |
39 | var bus = container.Resolve();
40 |
41 | Console.WriteLine("Sending message");
42 | await bus.SendLocal("hej søtte!");
43 |
44 | Console.WriteLine("Waiting for message to arrive in queue 'done'...");
45 | await network.WaitForNextMessageFrom("done");
46 | Console.WriteLine("Got the message!");
47 |
48 | Assert.That(stuff.Count, Is.EqualTo(1),
49 | "Expected second level handler to have been called only once!!");
50 | }
51 |
52 | class MyTestHandler : IHandleMessages, IHandleMessages>
53 | {
54 | readonly ConcurrentQueue _stuff;
55 | readonly IBus _bus;
56 |
57 | public MyTestHandler(ConcurrentQueue stuff, IBus bus)
58 | {
59 | _stuff = stuff ?? throw new ArgumentNullException(nameof(stuff));
60 | _bus = bus ?? throw new ArgumentNullException(nameof(bus));
61 | }
62 |
63 | public async Task Handle(IFailed message)
64 | {
65 | Console.WriteLine("2nd level handler running");
66 | _stuff.Enqueue($"Handled failed message: {message.Message}");
67 | await _bus.Advanced.Routing.Send("done", "we're done now");
68 | }
69 |
70 | public async Task Handle(string message)
71 | {
72 | Console.WriteLine("Throwing an exception now!");
73 | throw new NotImplementedException("OH NOES");
74 | }
75 | }
76 | }
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/Bugs/DoesNotTryToHandleMessagesBeforeTheBusIsProperlyStarted.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Threading.Tasks;
3 | using Autofac;
4 | using NUnit.Framework;
5 | using Rebus.Activation;
6 | using Rebus.Bus;
7 | using Rebus.Config;
8 | using Rebus.Handlers;
9 | using Rebus.Logging;
10 | using Rebus.Tests.Contracts;
11 | using Rebus.Tests.Contracts.Extensions;
12 | using Rebus.Tests.Contracts.Utilities;
13 | using Rebus.Transport.InMem;
14 | // ReSharper disable RedundantArgumentDefaultValue
15 | // ReSharper disable ClassNeverInstantiated.Local
16 | // ReSharper disable ArgumentsStyleLiteral
17 | #pragma warning disable 1998
18 |
19 | namespace Rebus.Autofac.Tests.Bugs;
20 |
21 | [TestFixture]
22 | public class DoesNotTryToHandleMessagesBeforeTheBusIsProperlyStarted : FixtureBase
23 | {
24 | [Test]
25 | [Repeat(10)]
26 | public async Task ItWorks()
27 | {
28 | const string queueName = "testappqueue";
29 | const int numberOfMessages = 10;
30 |
31 | var network = new InMemNetwork();
32 | var listLoggerFactory = new ListLoggerFactory(detailed: true);
33 | var sharedCounter = new SharedCounter(numberOfMessages);
34 |
35 | Using(sharedCounter);
36 |
37 | // deliver a message for our endpoint
38 | network.CreateQueue(queueName);
39 |
40 | var client = GetOneWayClient(network, listLoggerFactory);
41 |
42 | numberOfMessages.Times(() => client.Advanced.Routing.Send(queueName, "HEJ MED DIG MIN VEN").Wait());
43 |
44 | // prepare our endpoint
45 | var builder = new ContainerBuilder();
46 |
47 | builder.RegisterRebus(
48 | config => config
49 | .Logging(l => l.Use(listLoggerFactory))
50 | .Transport(t => t.UseInMemoryTransport(network, queueName))
51 | .Options(o =>
52 | {
53 | o.SetNumberOfWorkers(1);
54 | o.SetMaxParallelism(30);
55 | })
56 | );
57 | // obtain bus instance for subscriptions...
58 | builder.RegisterBuildCallback(c => {
59 | var bus = c.Resolve();
60 | });
61 |
62 | builder.RegisterHandler();
63 |
64 | builder.RegisterInstance(sharedCounter);
65 |
66 | // start it
67 | using (builder.Build())
68 | {
69 | sharedCounter.WaitForResetEvent(timeoutSeconds: 5);
70 | }
71 |
72 | // ensure no exceptions occurred
73 |
74 | Assert.That(listLoggerFactory.Count(log => log.Level >= LogLevel.Warn), Is.EqualTo(0),
75 | "Expected exactly ZERO warnings");
76 | }
77 |
78 | IBus GetOneWayClient(InMemNetwork network, ListLoggerFactory listLoggerFactory)
79 | {
80 | var activator = new BuiltinHandlerActivator();
81 |
82 | Using(activator);
83 |
84 | return Configure.With(activator)
85 | .Logging(l => l.Use(listLoggerFactory))
86 | .Transport(t => t.UseInMemoryTransportAsOneWayClient(network))
87 | .Start();
88 | }
89 |
90 | class MyMessageHandler : IHandleMessages
91 | {
92 | readonly SharedCounter _sharedCounter;
93 |
94 | public MyMessageHandler(SharedCounter sharedCounter) => _sharedCounter = sharedCounter;
95 |
96 | public async Task Handle(string message) => _sharedCounter.Decrement();
97 | }
98 | }
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/Bugs/RegistersHandlerAsImplementationOfIFailedForDerivedMessagesToo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Autofac;
7 | using Autofac.Features.Variance;
8 | using NUnit.Framework;
9 | using Rebus.Bus;
10 | using Rebus.Config;
11 | using Rebus.Handlers;
12 | using Rebus.Retry;
13 | using Rebus.Retry.Simple;
14 | using Rebus.Tests.Contracts;
15 | using Rebus.Transport;
16 | using Rebus.Transport.InMem;
17 | #pragma warning disable 1998
18 |
19 | namespace Rebus.Autofac.Tests.Bugs;
20 |
21 | [TestFixture]
22 | public class RegistersHandlerAsImplementationOfIFailedForDerivedMessagesToo : FixtureBase
23 | {
24 | private class BaseMessage
25 | {
26 | }
27 |
28 | private class DerivedMessage : BaseMessage
29 | {
30 | }
31 |
32 | [Test, Description("Verifies that a bus using Autofac and Rebus' handler registration API CAN in fact received failed messages")]
33 | public async Task DoItWithTheBus()
34 | {
35 | var builder = new ContainerBuilder();
36 |
37 | builder.RegisterSource(new ContravariantRegistrationSource());
38 |
39 | builder.RegisterRebus(configurer => configurer
40 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "2nd-level-test"))
41 | .Options(o => o.RetryStrategy(
42 | secondLevelRetriesEnabled: true,
43 | maxDeliveryAttempts: 1
44 | ))
45 | );
46 |
47 | builder.RegisterHandler();
48 |
49 | var failedMessageWasReceived = new ManualResetEvent(false);
50 |
51 | builder.RegisterInstance(failedMessageWasReceived);
52 |
53 | using (var container = builder.Build())
54 | {
55 | await container.Resolve().SendLocal(new DerivedMessage());
56 |
57 | if (!failedMessageWasReceived.WaitOne(TimeSpan.FromSeconds(5)))
58 | {
59 | throw new AssertionException("Failed message was NOT received within 5s timeout!");
60 | }
61 | }
62 | }
63 |
64 | class SecondLevelHandler : IHandleMessages, IHandleMessages>
65 | {
66 | readonly ManualResetEvent _gotTheFailedMessage;
67 |
68 | public SecondLevelHandler(ManualResetEvent gotTheFailedMessage) => _gotTheFailedMessage = gotTheFailedMessage;
69 |
70 | public Task Handle(BaseMessage message) => throw new NotImplementedException("MUAHAHAHAHAHA");
71 |
72 | public async Task Handle(IFailed message) => _gotTheFailedMessage.Set();
73 | }
74 |
75 | [Test]
76 | [Ignore("This logic is implemented in AutofacHandlerActivator as some additional logic, which is triggered when a message compatible with IFailed is detected")]
77 | public async Task ReadTheFixtureName()
78 | {
79 | var builder = new ContainerBuilder();
80 |
81 | builder.RegisterHandler();
82 |
83 | builder.RegisterSource(new ContravariantRegistrationSource());
84 |
85 | using (var container = builder.Build())
86 | {
87 | var ordinaryHandlers = container.Resolve>>();
88 | var failedMessageHandlers = container.Resolve>>>();
89 |
90 | Assert.That(ordinaryHandlers.Count(), Is.EqualTo(1));
91 | Assert.That(failedMessageHandlers.Count(), Is.EqualTo(1));
92 | }
93 | }
94 |
95 | [Test]
96 | public async Task ResolvesFailedOfBaseClass_FailedMessageWrapper()
97 | {
98 | var builder = new ContainerBuilder();
99 | builder.RegisterSource(new ContravariantRegistrationSource());
100 | builder.RegisterHandler();
101 |
102 | var activator = new AutofacHandlerActivator(builder, (_, __) => { }, startBus: false, enablePolymorphicDispatch: true, multipleRegistrationsCheckEnabled: true);
103 | using (var container = builder.Build())
104 | using (var scope = new RebusTransactionScope())
105 | {
106 | var handlers = await activator.GetHandlers(null, scope.TransactionContext);
107 | Assert.That(handlers, Is.Not.Empty, "resolving handlers for derived messages failed");
108 |
109 | var handlersFailed = await activator.GetHandlers>(null, scope.TransactionContext);
110 | Assert.That(handlersFailed, Is.Not.Empty, "resolving handlers for failed derived messages failed");
111 | }
112 | }
113 |
114 | [Test]
115 | public async Task ResolvesFailedOfBaseClass_SpecialWrapper()
116 | {
117 | var builder = new ContainerBuilder();
118 | builder.RegisterSource(new ContravariantRegistrationSource());
119 | builder.RegisterHandler();
120 |
121 | var activator = new AutofacHandlerActivator(builder, (_, __) => { }, startBus: false, enablePolymorphicDispatch: true, multipleRegistrationsCheckEnabled: true);
122 | using (var container = builder.Build())
123 | using (var scope = new RebusTransactionScope())
124 | {
125 | var handlers = await activator.GetHandlers(null, scope.TransactionContext);
126 | Assert.That(handlers, Is.Not.Empty, "resolving handlers for derived messages failed");
127 |
128 | var handlersFailed = await activator.GetHandlers(null, scope.TransactionContext);
129 | Assert.That(handlersFailed, Is.Not.Empty, "resolving handlers for failed derived messages failed");
130 | }
131 | }
132 |
133 | [Test]
134 | public async Task ResolvesFailedOfBaseClass_FailedInterface()
135 | {
136 | var builder = new ContainerBuilder();
137 | builder.RegisterSource(new ContravariantRegistrationSource());
138 | builder.RegisterHandler();
139 |
140 | var activator = new AutofacHandlerActivator(builder, (_, __) => { }, startBus: false, enablePolymorphicDispatch: true, multipleRegistrationsCheckEnabled: true);
141 | using (var container = builder.Build())
142 | using (var scope = new RebusTransactionScope())
143 | {
144 | var handlers = await activator.GetHandlers(null, scope.TransactionContext);
145 | Assert.That(handlers, Is.Not.Empty, "resolving handlers for derived messages failed");
146 |
147 | var handlersFailed = await activator.GetHandlers>(null, scope.TransactionContext);
148 | Assert.That(handlersFailed, Is.Not.Empty, "resolving handlers for failed derived messages failed");
149 | }
150 | }
151 |
152 | private class SpecialFailedMessage : IFailed
153 | {
154 | public DerivedMessage Message { get; set; }
155 | public string ErrorDescription { get; }
156 | public Dictionary Headers { get; set; }
157 | public IEnumerable Exceptions { get; set; }
158 | }
159 |
160 | public class FailedMessage : IFailed
161 | {
162 | public FailedMessage(T message, string errorDescription, Dictionary headers, IEnumerable exceptions)
163 | {
164 | Message = message;
165 | ErrorDescription = errorDescription;
166 | Headers = headers;
167 | Exceptions = exceptions;
168 | }
169 |
170 | public T Message { get; }
171 | public string ErrorDescription { get; }
172 | public Dictionary Headers { get; }
173 | public IEnumerable Exceptions { get; }
174 | }
175 |
176 | class TestHandler : IHandleMessages, IHandleMessages>
177 | {
178 | public Task Handle(BaseMessage message)
179 | {
180 | throw new System.NotImplementedException();
181 | }
182 |
183 | public Task Handle(IFailed message)
184 | {
185 | throw new System.NotImplementedException();
186 | }
187 | }
188 | }
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/Bugs/RegistersHandlerAsImplementationOfIFailedToo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Autofac;
7 | using Autofac.Features.Variance;
8 | using NUnit.Framework;
9 | using Rebus.Bus;
10 | using Rebus.Config;
11 | using Rebus.Handlers;
12 | using Rebus.Retry;
13 | using Rebus.Retry.Simple;
14 | using Rebus.Tests.Contracts;
15 | using Rebus.Transport;
16 | using Rebus.Transport.InMem;
17 | #pragma warning disable 1998
18 |
19 | namespace Rebus.Autofac.Tests.Bugs;
20 |
21 | [TestFixture]
22 | public class RegistersHandlerAsImplementationOfIFailedToo : FixtureBase
23 | {
24 | [Test, Description("Verifies that a bus using Autofac and Rebus' handler registration API CAN in fact received failed messages")]
25 | public async Task DoItWithTheBus()
26 | {
27 | var builder = new ContainerBuilder();
28 |
29 | builder.RegisterSource(new ContravariantRegistrationSource());
30 |
31 | builder.RegisterRebus(configurer => configurer
32 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "2nd-level-test"))
33 | .Options(o => o.RetryStrategy(
34 | secondLevelRetriesEnabled: true,
35 | maxDeliveryAttempts: 1
36 | ))
37 | );
38 |
39 | builder.RegisterHandler();
40 |
41 | var failedMessageWasReceived = new ManualResetEvent(false);
42 |
43 | builder.RegisterInstance(failedMessageWasReceived);
44 |
45 | using (var container = builder.Build())
46 | {
47 | await container.Resolve().SendLocal("HEJ MED DIG MIN VEN");
48 |
49 | if (!failedMessageWasReceived.WaitOne(TimeSpan.FromSeconds(5)))
50 | {
51 | throw new AssertionException("Failed message was NOT received within 5s timeout!");
52 | }
53 | }
54 | }
55 |
56 | class SecondLevelHandler : IHandleMessages, IHandleMessages>
57 | {
58 | readonly ManualResetEvent _gotTheFailedMessage;
59 |
60 | public SecondLevelHandler(ManualResetEvent gotTheFailedMessage) => _gotTheFailedMessage = gotTheFailedMessage;
61 |
62 | public Task Handle(string message) => throw new NotImplementedException("MUAHAHAHAHAHA");
63 |
64 | public async Task Handle(IFailed message) => _gotTheFailedMessage.Set();
65 | }
66 |
67 | [Test]
68 | public async Task ReadTheFixtureName()
69 | {
70 | var builder = new ContainerBuilder();
71 |
72 | builder.RegisterHandler();
73 |
74 | using (var container = builder.Build())
75 | {
76 | var ordinaryHandlers = container.Resolve>>();
77 | var failedMessageHandlers = container.Resolve>>>();
78 |
79 | Assert.That(ordinaryHandlers.Count(), Is.EqualTo(1));
80 | Assert.That(failedMessageHandlers.Count(), Is.EqualTo(1));
81 | }
82 | }
83 |
84 | [Test]
85 | public async Task ResolvesFailedOfBaseClass()
86 | {
87 | var builder = new ContainerBuilder();
88 | builder.RegisterHandler();
89 |
90 | var activator = new AutofacHandlerActivator(builder, (_, __) => { }, startBus: false, enablePolymorphicDispatch: true, multipleRegistrationsCheckEnabled: true);
91 | using (var container = builder.Build())
92 | using (var scope = new RebusTransactionScope())
93 | {
94 | var handlers = await activator.GetHandlers(null, scope.TransactionContext);
95 | Assert.That(handlers, Is.Not.Empty, "resolving handlers for derived messages failed");
96 |
97 | var handlersFailed = await activator.GetHandlers>(null, scope.TransactionContext);
98 | Assert.That(handlersFailed, Is.Not.Empty, "resolving handlers for failed derived messages failed");
99 | }
100 | }
101 |
102 | public class FailedMessage : IFailed
103 | {
104 | public FailedMessage(T message, string errorDescription, Dictionary headers, IEnumerable exceptions)
105 | {
106 | Message = message;
107 | ErrorDescription = errorDescription;
108 | Headers = headers;
109 | Exceptions = exceptions;
110 | }
111 |
112 | public T Message { get; }
113 | public string ErrorDescription { get; }
114 | public Dictionary Headers { get; }
115 | public IEnumerable Exceptions { get; }
116 | }
117 |
118 | class TestHandler : IHandleMessages, IHandleMessages>
119 | {
120 | public Task Handle(string message)
121 | {
122 | throw new System.NotImplementedException();
123 | }
124 |
125 | public Task Handle(IFailed message)
126 | {
127 | throw new System.NotImplementedException();
128 | }
129 | }
130 | }
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/Bugs/ReproduceDoubleDispatchIssue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Threading.Tasks;
4 | using AdditionalHandlerAssembly;
5 | using Autofac;
6 | using NUnit.Framework;
7 | using Rebus.Bus;
8 | using Rebus.Config;
9 | using Rebus.Retry.Simple;
10 | using Rebus.Tests.Contracts;
11 | using Rebus.Tests.Contracts.Extensions;
12 | using Rebus.Transport.InMem;
13 |
14 | namespace Rebus.Autofac.Tests.Bugs;
15 |
16 | [TestFixture]
17 | public class ReproduceDoubleDispatchIssue : FixtureBase
18 | {
19 | [Test]
20 | [Description("Tried to reproduce issue reported: Messages should apparently be dispatched twice. Sp far, reproduction has not been not successful.")]
21 | public async Task ItWorks()
22 | {
23 | var controllerChangeMessages = new ConcurrentQueue();
24 |
25 | var builder = new ContainerBuilder();
26 |
27 | builder.RegisterRebus((configurer, _) =>
28 | {
29 | var queueName = "queue";
30 |
31 | configurer
32 | .Logging(l => l.ColoredConsole())
33 | .Transport(x => x.UseInMemoryTransport(new InMemNetwork(true), queueName))
34 | .Options(x =>
35 | {
36 | x.SetMaxParallelism(1);
37 | x.RetryStrategy(maxDeliveryAttempts: int.MaxValue);
38 | });
39 |
40 | return configurer;
41 | });
42 |
43 | builder.RegisterHandlersFromAssemblyOf();
44 |
45 | builder.RegisterInstance(controllerChangeMessages).AsSelf();
46 |
47 | await using var container = builder.Build();
48 |
49 | var bus = container.Resolve();
50 |
51 | await bus.SendLocal(new ControllerChangeMessage());
52 |
53 | // wait for at least one message to arrive
54 | await controllerChangeMessages.WaitUntil(q => q.Count >= 1);
55 |
56 | // wait additional time to be sure all messages have been processed
57 | await Task.Delay(TimeSpan.FromSeconds(2));
58 |
59 | // even at this point, the handler should only have been called once!
60 | Assert.That(controllerChangeMessages.Count, Is.EqualTo(1));
61 | }
62 | }
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/CheckNewApi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Autofac;
3 | using NUnit.Framework;
4 | using Rebus.Bus;
5 | using Rebus.Config;
6 | using Rebus.Logging;
7 | using Rebus.Tests.Contracts;
8 | using Rebus.Tests.Contracts.Utilities;
9 | using Rebus.Transport.InMem;
10 | // ReSharper disable RedundantArgumentDefaultValue
11 | // ReSharper disable ArgumentsStyleNamedExpression
12 |
13 | namespace Rebus.Autofac.Tests;
14 |
15 | [TestFixture]
16 | public class CheckNewApi : FixtureBase
17 | {
18 | [Test]
19 | public void ThisIsHowItWorks_StartsAutomatically()
20 | {
21 | var builder = new ContainerBuilder();
22 |
23 | builder.RegisterRebus(
24 | configure => configure
25 | .Logging(l => l.Console(minLevel: LogLevel.Debug))
26 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "ioc-test"))
27 | );
28 |
29 | var container = builder.Build();
30 |
31 | Using(container);
32 |
33 | var bus = container.Resolve();
34 |
35 | Assert.That(bus.Advanced.Workers.Count, Is.EqualTo(1));
36 | }
37 |
38 | [Test]
39 | public void ThisIsHowItWorks_StartManually()
40 | {
41 | var builder = new ContainerBuilder();
42 |
43 | builder.RegisterRebus(
44 | configure => configure
45 | .Logging(l => l.Console(minLevel: LogLevel.Debug))
46 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "ioc-test")),
47 |
48 | startAutomatically: false
49 | );
50 |
51 | var container = builder.Build();
52 |
53 | Using(container);
54 |
55 | var bus = container.Resolve();
56 |
57 | Assert.That(bus.Advanced.Workers.Count, Is.EqualTo(0));
58 |
59 | container.StartBus();
60 |
61 | Assert.That(bus.Advanced.Workers.Count, Is.EqualTo(1));
62 | }
63 |
64 | [Test]
65 | public void ThisIsHowItWorks()
66 | {
67 | var builder = new ContainerBuilder();
68 |
69 | builder.RegisterRebus(
70 | configure => configure
71 | .Logging(l => l.Console(minLevel: LogLevel.Debug))
72 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "ioc-test"))
73 | );
74 |
75 | var container = builder.Build();
76 |
77 | Using(container);
78 | }
79 |
80 | [Test]
81 | public void ThisIsHowItWorks_ComponentContext()
82 | {
83 | var builder = new ContainerBuilder();
84 |
85 | builder.Register(_ => new ListLoggerFactory(outputToConsole: true));
86 |
87 | builder.RegisterRebus(
88 | (configure, context) => configure
89 | .Logging(l => l.Use(context.Resolve()))
90 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "ioc-test"))
91 | );
92 |
93 | var container = builder.Build();
94 |
95 | Using(container);
96 | }
97 |
98 | [Test]
99 | public void ThrowsWhenAddingTwice()
100 | {
101 | var builder = new ContainerBuilder();
102 |
103 | builder.RegisterRebus(configure => configure
104 | .Logging(l => l.Console(minLevel: LogLevel.Debug))
105 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "ioc-test")));
106 |
107 | builder.RegisterRebus(configure => configure
108 | .Logging(l => l.Console(minLevel: LogLevel.Debug))
109 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "ioc-test")));
110 |
111 | Assert.Throws(() => builder.Build());
112 | }
113 |
114 | [Test]
115 | public void DoesNotThrowWhenRegisteringTwiceIfExplicitlyDisabled()
116 | {
117 | var builder = new ContainerBuilder();
118 |
119 | builder.RegisterRebus(configure => configure
120 | .Logging(l => l.Console(minLevel: LogLevel.Debug))
121 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "ioc-test")),
122 | disableMultipleRegistrationsCheck: true);
123 |
124 | builder.RegisterRebus(configure => configure
125 | .Logging(l => l.Console(minLevel: LogLevel.Debug))
126 | .Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "ioc-test")),
127 | disableMultipleRegistrationsCheck: true);
128 |
129 | Assert.DoesNotThrow(() => builder.Build());
130 | }
131 | }
--------------------------------------------------------------------------------
/Rebus.Autofac.Tests/CheckResolutionPerformance.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Autofac;
7 | using NUnit.Framework;
8 | using Rebus.Config;
9 | using Rebus.Handlers;
10 | using Rebus.Transport;
11 | // ReSharper disable ArgumentsStyleLiteral
12 |
13 | namespace Rebus.Autofac.Tests;
14 |
15 | [TestFixture]
16 | public class CheckResolutionPerformance
17 | {
18 | /*
19 | Initially:
20 |
21 |
22 | Running 10 samples of 1000000 iterations
23 | Running sample # 1
24 | Running sample # 2
25 | Running sample # 3
26 | Running sample # 4
27 | Running sample # 5
28 | Running sample # 6
29 | Running sample # 7
30 | Running sample # 8
31 | Running sample # 9
32 | Running sample # 10
33 | Results:
34 |
35 | 5,088 s
36 | 4,909 s
37 | 4,677 s
38 | 4,668 s
39 | 4,524 s
40 | 4,500 s
41 | 4,477 s
42 | 4,457 s
43 | 4,466 s
44 | 4,482 s
45 |
46 | AVG: 4,625
47 |
48 | After caching types to resolve in ConcurrentDictionary:
49 |
50 |
51 | Running 10 samples of 1000000 iterations
52 | Running sample # 1
53 | Running sample # 2
54 | Running sample # 3
55 | Running sample # 4
56 | Running sample # 5
57 | Running sample # 6
58 | Running sample # 7
59 | Running sample # 8
60 | Running sample # 9
61 | Running sample # 10
62 | Results:
63 |
64 | 4,312 s
65 | 4,274 s
66 | 4,282 s
67 | 4,466 s
68 | 4,450 s
69 | 4,593 s
70 | 4,291 s
71 | 4,256 s
72 | 4,548 s
73 | 4,470 s
74 |
75 | AVG: 4,394
76 |
77 |
78 | Refactor to local functions and collapsed typecast into one single cast:
79 |
80 |
81 | Running 10 samples of 1000000 iterations
82 | Running sample # 1
83 | Running sample # 2
84 | Running sample # 3
85 | Running sample # 4
86 | Running sample # 5
87 | Running sample # 6
88 | Running sample # 7
89 | Running sample # 8
90 | Running sample # 9
91 | Running sample # 10
92 | Results:
93 |
94 | 3,906 s
95 | 3,905 s
96 | 3,911 s
97 | 3,883 s
98 | 3,899 s
99 | 3,893 s
100 | 4,668 s
101 | 4,027 s
102 | 4,017 s
103 | 4,147 s
104 |
105 | AVG: 4,026
106 |
107 |
108 |
109 | */
110 | [TestCase(10, 1000000)]
111 | [TestCase(10, 10000)]
112 | [Explicit("takes a long time")]
113 | public async Task Run(int samples, int ops)
114 | {
115 | Console.WriteLine($"Running {samples} samples of {ops} iterations");
116 |
117 | var builder = new ContainerBuilder();
118 |
119 | builder.RegisterHandler();
120 | builder.RegisterHandler();
121 | builder.RegisterHandler();
122 |
123 | var activator = new AutofacHandlerActivator(builder, (_, _) => { }, startBus: false, enablePolymorphicDispatch: true, multipleRegistrationsCheckEnabled: true);
124 | var timeSpans = new List();
125 |
126 | await using (builder.Build())
127 | {
128 | foreach (var sample in Enumerable.Range(1, samples))
129 | {
130 | var elapsed = await TakeSample(sample, ops, activator);
131 |
132 | timeSpans.Add(elapsed);
133 | }
134 | }
135 |
136 | Console.WriteLine($@"Results:
137 |
138 | {string.Join(Environment.NewLine, timeSpans.Select(t => $" {t.TotalSeconds:0.000} s"))}
139 |
140 | AVG: {timeSpans.Select(t => t.TotalSeconds).Average():0.000}");
141 | }
142 |
143 | static async Task TakeSample(int sample, int ops, AutofacHandlerActivator activator)
144 | {
145 | Console.WriteLine($"Running sample # {sample}");
146 |
147 | var stopwatch = Stopwatch.StartNew();
148 |
149 | for (var counter = 0; counter < ops; counter++)
150 | {
151 | using (var scope = new RebusTransactionScope())
152 | {
153 | var handlers1 = await activator.GetHandlers(new OrdinaryMessage(), scope.TransactionContext);
154 | }
155 |
156 | using (var scope = new RebusTransactionScope())
157 | {
158 | var handlers2 = await activator.GetHandlers(new PolymorphicMessage(), scope.TransactionContext);
159 | }
160 | }
161 |
162 | return stopwatch.Elapsed;
163 | }
164 |
165 | class OrdinaryMessage { }
166 |
167 | class OrdinaryMessageHandler : IHandleMessages
168 | {
169 | public Task Handle(OrdinaryMessage message)
170 | {
171 | throw new NotImplementedException();
172 | }
173 | }
174 |
175 | class PolymorphicMessage { }
176 |
177 | class PolymorphicMessageHandler : IHandleMessages
178 | {
179 | public Task Handle(PolymorphicMessage message)
180 | {
181 | throw new NotImplementedException();
182 | }
183 | }
184 |
185 | class PolymorphicMessageHandler2 : IHandleMessages