diff --git a/test/MediatR.Benchmarks/Benchmarks.cs b/test/MediatR.Benchmarks/Benchmarks.cs
index ae82f2ad..849066a2 100644
--- a/test/MediatR.Benchmarks/Benchmarks.cs
+++ b/test/MediatR.Benchmarks/Benchmarks.cs
@@ -1,7 +1,6 @@
using System.IO;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
-using MediatR.Pipeline;
using Microsoft.Extensions.DependencyInjection;
namespace MediatR.Benchmarks
@@ -20,11 +19,11 @@ public void GlobalSetup()
services.AddSingleton(TextWriter.Null);
- services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining(typeof(Ping)));
-
- services.AddScoped(typeof(IPipelineBehavior<,>), typeof(GenericPipelineBehavior<,>));
- services.AddScoped(typeof(IRequestPreProcessor<>), typeof(GenericRequestPreProcessor<>));
- services.AddScoped(typeof(IRequestPostProcessor<,>), typeof(GenericRequestPostProcessor<,>));
+ services.AddMediatR(cfg =>
+ {
+ cfg.RegisterServicesFromAssemblyContaining(typeof(Ping));
+ cfg.AddOpenBehavior(typeof(GenericPipelineBehavior<,>));
+ });
var provider = services.BuildServiceProvider();
diff --git a/test/MediatR.Benchmarks/DotTraceDiagnoser.cs b/test/MediatR.Benchmarks/DotTraceDiagnoser.cs
index 38d66647..65999eeb 100644
--- a/test/MediatR.Benchmarks/DotTraceDiagnoser.cs
+++ b/test/MediatR.Benchmarks/DotTraceDiagnoser.cs
@@ -29,12 +29,14 @@ public DotTraceDiagnoserAttribute()
internal sealed class DotTraceDiagnoser : IDiagnoser
{
- private Process _process;
- private string _saveLocation;
+ private const string DotTraceExecutableNotFoundErrorMessage = "dotTrace executable was not found. " +
+ "Make sure it is part of the PATH or install JetBrains.dotTrace.GlobalTools";
+
+ private readonly string _saveLocation;
public DotTraceDiagnoser()
{
- _saveLocation = $"C:\\temp\\MyProject\\{DateTimeOffset.Now.UtcDateTime:yyyyMMddTHHmmss}.bench.dtp";
+ _saveLocation = $"C:\\temp\\MediatR\\{DateTimeOffset.Now.UtcDateTime:yyyy-MM-dd-HH_mm_ss}.bench.dtp";
}
///
@@ -43,60 +45,58 @@ public DotTraceDiagnoser()
///
public void Handle(HostSignal signal, DiagnoserActionParameters parameters)
{
- switch (signal)
+ if (signal != HostSignal.BeforeActualRun)
+ {
+ return;
+ }
+
+ try
+ {
+ if (!CanRunDotTrace())
+ {
+ Console.WriteLine(DotTraceExecutableNotFoundErrorMessage);
+ return;
+ }
+
+ // The directory must exist or an error is thrown by dotTrace.
+ Directory.CreateDirectory(_saveLocation);
+ RunDotTrace(parameters);
+ }
+ catch (Exception e)
{
- case HostSignal.BeforeActualRun:
- try
- {
- var dotTracePath = Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- @"JetBrains\Installations\dotTrace192\ConsoleProfiler.exe");
- var startInfo = new ProcessStartInfo(
- dotTracePath,
- $"attach {parameters.Process.Id} --save-to={_saveLocation} --profiling-type=Sampling")
- {
- RedirectStandardError
- = true,
- RedirectStandardOutput = true,
- WindowStyle = ProcessWindowStyle.Normal,
- UseShellExecute = false,
- };
- Console.WriteLine(startInfo.FileName);
- Console.WriteLine(startInfo.Arguments);
- _process = new Process
- {
- StartInfo = startInfo
- };
- _process.ErrorDataReceived += (sender, eventArgs) => Console.Error.WriteLine(eventArgs.Data);
- _process.OutputDataReceived += (sender, eventArgs) => Console.WriteLine(eventArgs.Data);
- _process.Start();
- _process.BeginErrorReadLine();
- _process.BeginOutputReadLine();
- _process.Exited += (sender, args) => { _process.Dispose(); };
- }
- catch (Exception e)
- {
- Console.Error.WriteLine(e.StackTrace);
- throw;
- }
- break;
- case HostSignal.AfterActualRun:
- break;
- case HostSignal.BeforeAnythingElse:
- break;
- case HostSignal.AfterAll:
- break;
- case HostSignal.SeparateLogic:
- break;
- case HostSignal.BeforeProcessStart:
- break;
- case HostSignal.AfterProcessExit:
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(signal), signal, null);
+ Console.Error.WriteLine(e.ToString());
+ throw;
}
}
+ private void RunDotTrace(DiagnoserActionParameters parameters)
+ {
+ var dotTrace = new Process
+ {
+ StartInfo = PrepareProcessStartInfo(parameters)
+ };
+ dotTrace.ErrorDataReceived += (sender, eventArgs) => Console.Error.WriteLine(eventArgs.Data);
+ dotTrace.OutputDataReceived += (sender, eventArgs) => Console.WriteLine(eventArgs.Data);
+ dotTrace.Start();
+ dotTrace.BeginErrorReadLine();
+ dotTrace.BeginOutputReadLine();
+ dotTrace.Exited += (sender, args) => dotTrace.Dispose();
+ }
+
+ private ProcessStartInfo PrepareProcessStartInfo(DiagnoserActionParameters parameters)
+ {
+ return new ProcessStartInfo(
+ "dottrace",
+ $"attach {parameters.Process.Id} --save-to={_saveLocation}")
+ {
+ RedirectStandardError = true,
+ RedirectStandardOutput = true,
+ WindowStyle = ProcessWindowStyle.Hidden,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ };
+ }
+
///
public IEnumerable ProcessResults(DiagnoserResults results) => Enumerable.Empty();
@@ -114,5 +114,29 @@ public IEnumerable Validate(ValidationParameters validationPara
public IEnumerable Exporters => Enumerable.Empty();
public IEnumerable Analysers { get; } = Enumerable.Empty();
+
+ private static bool CanRunDotTrace()
+ {
+ try
+ {
+ var startInfo = new ProcessStartInfo("dottrace")
+ {
+ RedirectStandardError = true,
+ RedirectStandardOutput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ };
+
+ using var process = new Process { StartInfo = startInfo };
+ process.Start();
+ process.WaitForExit();
+
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/test/MediatR.Benchmarks/GenericPipelineBehavior.cs b/test/MediatR.Benchmarks/GenericPipelineBehavior.cs
index 26ffd59e..52577095 100644
--- a/test/MediatR.Benchmarks/GenericPipelineBehavior.cs
+++ b/test/MediatR.Benchmarks/GenericPipelineBehavior.cs
@@ -5,7 +5,7 @@
namespace MediatR.Benchmarks
{
public class GenericPipelineBehavior : IPipelineBehavior
- where TRequest : IRequest
+ where TRequest : notnull
{
private readonly TextWriter _writer;
diff --git a/test/MediatR.Benchmarks/GenericRequestPostProcessor.cs b/test/MediatR.Benchmarks/GenericRequestPostProcessor.cs
index f8ae0f53..c657a07a 100644
--- a/test/MediatR.Benchmarks/GenericRequestPostProcessor.cs
+++ b/test/MediatR.Benchmarks/GenericRequestPostProcessor.cs
@@ -6,7 +6,7 @@
namespace MediatR.Benchmarks
{
public class GenericRequestPostProcessor : IRequestPostProcessor
- where TRequest : IRequest
+ where TRequest : notnull
{
private readonly TextWriter _writer;
diff --git a/test/MediatR.Benchmarks/GenericRequestPreProcessor.cs b/test/MediatR.Benchmarks/GenericRequestPreProcessor.cs
index a2079c4b..ee253100 100644
--- a/test/MediatR.Benchmarks/GenericRequestPreProcessor.cs
+++ b/test/MediatR.Benchmarks/GenericRequestPreProcessor.cs
@@ -6,6 +6,7 @@
namespace MediatR.Benchmarks
{
public class GenericRequestPreProcessor : IRequestPreProcessor
+ where TRequest : notnull
{
private readonly TextWriter _writer;
diff --git a/test/MediatR.Benchmarks/MediatR.Benchmarks.csproj b/test/MediatR.Benchmarks/MediatR.Benchmarks.csproj
index 0232c140..1946994d 100644
--- a/test/MediatR.Benchmarks/MediatR.Benchmarks.csproj
+++ b/test/MediatR.Benchmarks/MediatR.Benchmarks.csproj
@@ -2,8 +2,6 @@
net6.0
Exe
-
- 7.3
AnyCPU
@@ -14,8 +12,8 @@
Release
-
-
+
+
diff --git a/test/MediatR.Benchmarks/Ping.cs b/test/MediatR.Benchmarks/Ping.cs
index c1f40b3f..59566af7 100644
--- a/test/MediatR.Benchmarks/Ping.cs
+++ b/test/MediatR.Benchmarks/Ping.cs
@@ -1,7 +1,15 @@
+using System.Threading;
+using System.Threading.Tasks;
+
namespace MediatR.Benchmarks
{
public class Ping : IRequest
{
public string Message { get; set; }
}
+
+ public class PingHandler : IRequestHandler
+ {
+ public Task Handle(Ping request, CancellationToken cancellationToken) => Task.CompletedTask;
+ }
}
\ No newline at end of file
diff --git a/test/MediatR.Benchmarks/Pinged.cs b/test/MediatR.Benchmarks/Pinged.cs
index 09dada08..6ee38429 100644
--- a/test/MediatR.Benchmarks/Pinged.cs
+++ b/test/MediatR.Benchmarks/Pinged.cs
@@ -1,7 +1,17 @@
+using System.Threading;
+using System.Threading.Tasks;
+
namespace MediatR.Benchmarks
{
public class Pinged : INotification
{
+ }
+ public class PingedHandler : INotificationHandler
+ {
+ public Task Handle(Pinged notification, CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
}
}
\ No newline at end of file