Skip to content
This repository was archived by the owner on May 22, 2024. It is now read-only.

Commit ec2944b

Browse files
304NotModifiedmbhoek
authored andcommitted
Automatically register SpecFlow bindings (#25)
* Search for BindingAttribute inside lib * add AutoRegisterBindings Contributor: @304NotModified +semver: feature
1 parent df9f38c commit ec2944b

File tree

4 files changed

+33
-27
lines changed

4 files changed

+33
-27
lines changed

README.md

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,6 @@ PM> Install-Package SolidToken.SpecFlow.DependencyInjection
2323

2424
Create a static method somewhere in the SpecFlow project (recommended to put it into the ```Support``` folder) that returns an Microsoft.Extensions.DependencyInjection ```IServiceCollection``` and tag it with the `[ScenarioDependencies]` attribute. Configure your dependencies for the scenario execution within the method. You also have to register the step definition classes, that you can do by either registering all classes marked with the ```[Binding]``` attribute:
2525

26-
```csharp
27-
foreach (var type in typeof(TestDependencies).Assembly.GetTypes().Where(t => Attribute.IsDefined(t, typeof(BindingAttribute))))
28-
{
29-
services.AddSingleton(type);
30-
}
31-
```
32-
3326
A typical dependency builder method probably looks like this:
3427

3528
```csharp
@@ -38,13 +31,6 @@ public static IServiceCollection CreateServices()
3831
{
3932
var services = new ServiceCollection();
4033

41-
// TODO: add customizations, stubs required for testing
42-
43-
foreach (var type in typeof(TestDependencies).Assembly.GetTypes().Where(t => Attribute.IsDefined(t, typeof(BindingAttribute))))
44-
{
45-
services.AddSingleton(type);
46-
}
47-
4834
return services;
4935
}
5036
```

SpecFlow.DependencyInjection.Tests/TestDependencies.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Linq;
33
using Microsoft.Extensions.DependencyInjection;
4-
using TechTalk.SpecFlow;
54

65
namespace SolidToken.SpecFlow.DependencyInjection.Tests
76
{
@@ -18,14 +17,6 @@ public static IServiceCollection CreateServices()
1817
// ContextInjectionScope (by using AddScoped instead of AddTransient, the context will be scoped to the Feature across bindings)
1918
services.AddScoped<TestContext>();
2019

21-
// NOTE: This line is essential so that Microsoft.Extensions.DependencyInjection knows
22-
// about the SpecFlow bindings (something normally BoDi does automatically).
23-
// TODO: Find out if we can make this part of the Plugin
24-
foreach (var type in typeof(TestDependencies).Assembly.GetTypes().Where(t => Attribute.IsDefined(t, typeof(BindingAttribute))))
25-
{
26-
services.AddSingleton(type);
27-
}
28-
2920
return services;
3021
}
3122
}

SpecFlow.DependencyInjection/ScenarioDependenciesAttribute.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@ namespace SolidToken.SpecFlow.DependencyInjection
55
[AttributeUsage(AttributeTargets.Method)]
66
public class ScenarioDependenciesAttribute : Attribute
77
{
8+
/// <summary>
9+
/// Automatically register all SpecFlow bindings
10+
/// </summary>
11+
public bool AutoRegisterBindings { get; set; } = true;
812
}
913
}

SpecFlow.DependencyInjection/ServiceCollectionFinder.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using System.Reflection;
44
using Microsoft.Extensions.DependencyInjection;
5+
using TechTalk.SpecFlow;
56
using TechTalk.SpecFlow.Bindings;
67

78
namespace SolidToken.SpecFlow.DependencyInjection
@@ -34,15 +35,39 @@ protected virtual Func<IServiceCollection> FindCreateScenarioServiceCollection()
3435
{
3536
foreach (var type in assembly.GetTypes())
3637
{
37-
foreach (var methodInfo in type
38-
.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)
39-
.Where(m => Attribute.IsDefined((MemberInfo)m, typeof(ScenarioDependenciesAttribute))))
38+
foreach (var methodInfo in type.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
4039
{
41-
return () => (IServiceCollection)methodInfo.Invoke(null, null);
40+
var scenarioDependenciesAttribute = (ScenarioDependenciesAttribute)Attribute.GetCustomAttribute(methodInfo, typeof(ScenarioDependenciesAttribute));
41+
42+
if (scenarioDependenciesAttribute != null)
43+
{
44+
return () =>
45+
{
46+
var serviceCollection = GetServiceCollection(methodInfo);
47+
if (scenarioDependenciesAttribute.AutoRegisterBindings)
48+
{
49+
AddBindingAttributes(assembly, serviceCollection);
50+
}
51+
return serviceCollection;
52+
};
53+
}
4254
}
4355
}
4456
}
4557
return null;
4658
}
59+
60+
private static IServiceCollection GetServiceCollection(MethodBase methodInfo)
61+
{
62+
return (IServiceCollection)methodInfo.Invoke(null, null);
63+
}
64+
65+
private static void AddBindingAttributes(Assembly assembly, IServiceCollection serviceCollection)
66+
{
67+
foreach (var type in assembly.GetTypes().Where(t => Attribute.IsDefined(t, typeof(BindingAttribute))))
68+
{
69+
serviceCollection.AddSingleton(type);
70+
}
71+
}
4772
}
4873
}

0 commit comments

Comments
 (0)