Repository: dotnet/BenchmarkDotNet

Issue:
Multiple MarkdownExporters not possible
I'm testing BenchmarkDotNet and would like to have the benchmark results exported to both GitHub markdown and Atlassian markdown. But I get the error

```
The exporter BenchmarkDotNet.Exporters.MarkdownExporter is already present in configuration. There may be unexpected results.
```

Is that by intention - and why is it not possible to export to both markdown formats in the same run?


Hints:
> Is that by intention 

I really doubt that, it's most likely a bug on our side.
The issue is as far as I can see in the `ImmutableConfigBuilder.GetExporters` method. It makes a mergeDictionary by the System.Type - and that will be the same for both the GitHub MarkdownExporter and the Atlassian MarkdownExporter.

If the purpose is to avoid having for example GitHub MarkdownExporter twice in the merged list, I see the logic in going through the lists of exporters and remove duplicates. But it has to be on something else or more that just the System.Type.

Patch:
diff --git a/src/BenchmarkDotNet/Configs/ImmutableConfigBuilder.cs b/src/BenchmarkDotNet/Configs/ImmutableConfigBuilder.cs
index f5d857df1d..0540dd1426 100644
--- a/src/BenchmarkDotNet/Configs/ImmutableConfigBuilder.cs
+++ b/src/BenchmarkDotNet/Configs/ImmutableConfigBuilder.cs
@@ -109,28 +109,28 @@ void AddWarning(string message)
                 configAnalyse.Add(conclusion);
             }
 
-            var mergeDictionary = new Dictionary<System.Type, IExporter>();
+            var mergeDictionary = new Dictionary<string, IExporter>();
 
             foreach (var exporter in exporters)
             {
-                var exporterType = exporter.GetType();
-                if (mergeDictionary.ContainsKey(exporterType))
+                var exporterName = exporter.Name;
+                if (mergeDictionary.ContainsKey(exporterName))
                 {
-                    AddWarning($"The exporter {exporterType} is already present in configuration. There may be unexpected results.");
+                    AddWarning($"The exporter {exporterName} is already present in configuration. There may be unexpected results.");
                 }
-                mergeDictionary[exporterType] = exporter;
+                mergeDictionary[exporterName] = exporter;
             }
 
 
             foreach (var diagnoser in uniqueDiagnosers)
                 foreach (var exporter in diagnoser.Exporters)
                 {
-                    var exporterType = exporter.GetType();
-                    if (mergeDictionary.ContainsKey(exporterType))
+                    var exporterName = exporter.Name;
+                    if (mergeDictionary.ContainsKey(exporterName))
                     {
-                        AddWarning($"The exporter {exporterType} of {diagnoser.GetType().Name} is already present in configuration. There may be unexpected results.");
+                        AddWarning($"The exporter {exporterName} of {diagnoser.GetType().Name} is already present in configuration. There may be unexpected results.");
                     }
-                    mergeDictionary[exporterType] = exporter;
+                    mergeDictionary[exporterName] = exporter;
                 }
 
             var result = mergeDictionary.Values.ToList();
@@ -143,7 +143,7 @@ void AddWarning(string message)
             if (hardwareCounterDiagnoser != default(IHardwareCountersDiagnoser) && disassemblyDiagnoser != default(DisassemblyDiagnoser))
                 result.Add(new InstructionPointerExporter(hardwareCounterDiagnoser, disassemblyDiagnoser));
 
-            for (int i = result.Count - 1; i >=0; i--)
+            for (int i = result.Count - 1; i >= 0; i--)
                 if (result[i] is IExporterDependencies exporterDependencies)
                     foreach (var dependency in exporterDependencies.Dependencies)
                         /*
@@ -165,7 +165,7 @@ void AddWarning(string message)
                          *  "The CsvMeasurementsExporter is already present in the configuration. There may be unexpected results of RPlotExporter.
                          *
                          */
-                        if (!result.Any(exporter=> exporter.GetType() == dependency.GetType()))
+                        if (!result.Any(exporter => exporter.GetType() == dependency.GetType()))
                             result.Insert(i, dependency); // All the exporter dependencies should be added before the exporter
                         else
                         {
@@ -186,9 +186,9 @@ private static ImmutableHashSet<IAnalyser> GetAnalysers(IEnumerable<IAnalyser> a
                     builder.Add(analyser);
 
             foreach (var diagnoser in uniqueDiagnosers)
-            foreach (var analyser in diagnoser.Analysers)
-                if (!builder.Contains(analyser))
-                    builder.Add(analyser);
+                foreach (var analyser in diagnoser.Analysers)
+                    if (!builder.Contains(analyser))
+                        builder.Add(analyser);
 
             return builder.ToImmutable();
         }


Test patch:
diff --git a/tests/BenchmarkDotNet.Tests/Configs/ImmutableConfigTests.cs b/tests/BenchmarkDotNet.Tests/Configs/ImmutableConfigTests.cs
index 82c01d3b81..2eae58c7c1 100644
--- a/tests/BenchmarkDotNet.Tests/Configs/ImmutableConfigTests.cs
+++ b/tests/BenchmarkDotNet.Tests/Configs/ImmutableConfigTests.cs
@@ -143,6 +143,19 @@ public void DuplicateExportersAreExcluded()
             Assert.Same(MarkdownExporter.GitHub, final.GetExporters().Single());
         }
 
+        [Fact]
+        public void MultipleExportersOfSameTypeWithDifferentNamesAreAccepted()
+        {
+            var mutable = ManualConfig.CreateEmpty();
+
+            mutable.AddExporter(MarkdownExporter.GitHub);
+            mutable.AddExporter(MarkdownExporter.Atlassian);
+
+            var final = ImmutableConfigBuilder.Create(mutable);
+
+            Assert.Equal(2, final.GetExporters().Count());
+        }
+
         [Fact]
         public void DuplicateAnalyzersAreExcluded()
         {
@@ -380,7 +393,7 @@ private static ImmutableConfig[] AddLeftToTheRightAndRightToTheLef(ManualConfig
             var leftAddedToTheRight = ManualConfig.Create(right);
             leftAddedToTheRight.Add(left);
 
-            return new[]{ rightAddedToLeft.CreateImmutableConfig(), leftAddedToTheRight.CreateImmutableConfig() };
+            return new[] { rightAddedToLeft.CreateImmutableConfig(), leftAddedToTheRight.CreateImmutableConfig() };
         }
 
         public class TestExporter : IExporter, IExporterDependencies