Skip to content

Commit 01158f8

Browse files
committed
WIP docco #269
1 parent 6e42207 commit 01158f8

6 files changed

Lines changed: 72 additions & 62 deletions

File tree

CSF.Screenplay.Abstractions/IPersona.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@ namespace CSF.Screenplay
55
/// <summary>A persona is a factory for a commonly-used actor</summary>
66
/// <remarks>
77
/// <para>
8-
/// In Screenplay is is recommended to use memorable actors which are widely understood and recognisable
9-
/// by the team. This is easier if the composition of an actor is the same across every <see cref="IPerformance"/> in which
8+
/// In Screenplay is is recommended to use &amp; reuse memorable actors, which are widely understood and recognisable
9+
/// to the development team. This is easier if the composition of an actor is the same across every <see cref="IPerformance"/> in which
1010
/// they participate.
1111
/// </para>
1212
/// <para>
13-
/// By using a separate persona implementation for each named actor, the developer can ensure consistent creation
14-
/// for instances of those actors.
13+
/// Use classes which derive from this interface to define those memorable
14+
/// actors. The persona class should configure the actor it creates with a name and
15+
/// a set of abilities appropriate to the actor.
16+
/// </para>
17+
/// <para>
18+
/// Classes which derive from this interface should constructor-inject any dependencies
19+
/// they require, such as those required to grant abilities.
1520
/// </para>
1621
/// </remarks>
1722
public interface IPersona : IHasName
@@ -26,4 +31,4 @@ public interface IPersona : IHasName
2631
/// <param name="performanceIdentity">A unique identity for the currently-executing performance</param>
2732
Actor GetActor(Guid performanceIdentity);
2833
}
29-
}
34+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Injecting services into Personas
2+
Types which derive from [`IPersona`] support constructor-injected dependencies.
3+
Personas are typically used by either [the cast] or [the stage] to get an [Actor].
4+
The technique in which they are used means that they are resolved, along with their constructor-injected dependencies, from DI.
5+
6+
Use constructor-injected dependencies in persona classes to provide access to the APIs required to resolve [Abilities] that the actor is to be granted.
7+
8+
[`IPersona`]: xref:CSF.Screenplay.IPersona
9+
[the cast]: xref:CSF.Screenplay.ICast
10+
[the stage]: xref:CSF.Screenplay.IStage
11+
[Actor]: xref:CSF.Screenplay.Actor
12+
[Abilities]: ../../glossary/Ability.md
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Constructor injection for bindings
2+
For frameworks which are based on **binding classes** such as [Reqnroll], services are constructor-injected into binding classes.
3+
4+
Use dependencies injected in this way to get access to [commonly-used Screenplay services] and anything else required at the root level of your test logic.
5+
6+
[Reqnroll]: https://reqnroll.net/
7+
[commonly-used Screenplay services]: InjectableServices.md
Lines changed: 16 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,24 @@
11
---
22
uid: InjectingServicesArticle
33
---
4-
54
# Injecting services
65

7-
There are a few techniques in which injecting dependencies is relevant. These are summarised below.
8-
All but one of these techniques provide access to [the services which are added to the container].
9-
10-
[the services which are added to the container]: InjectableServices.md
11-
12-
## Into test logic
13-
14-
When using automated test logic based upon Screenplay, the use of dependency injection typically takes one of two forms.
15-
Which of these depends upon the nature and paradigm of the test framework.
16-
17-
For frameworks which are based on **test methods** such as [NUnit], services are typically injected via _method parameter injection_ into the test methods.
18-
[If Screenplay were to be extended] to work with frameworks such as xUnit or MSTest then this is likely to be the technique used.
19-
20-
For frameworks which are based on **binding classes** such as [Reqnroll], services are constructor-injected into binding classes.
21-
22-
Use dependencies injected in this way to get access to [commonly-used Screenplay services] and anything else required at the root level of your test logic.
23-
24-
[NUnit]: https://nunit.org/
25-
[If Screenplay were to be extended]: ../extendingScreenplay/TestIntegrations.md
26-
[Reqnroll]: https://reqnroll.net/
27-
[commonly-used Screenplay services]: InjectableServices.md
28-
29-
## Into standalone performance logic
6+
The table below summarises how to get services, from various contexts. In the first column are contexts/situations in which a developer could require services from DI. The second column indicates and links to the appropriate technique for that scenario.
307

31-
If you are [using Screenplay standalone] then the [`Screenplay.ExecuteAsPerformanceAsync`] permits resolution of dependencies via its parameter.
32-
That parameter is a `Func<IServiceProvider,CancellationToken,Task<bool?>>`.
33-
The service provider may be used to resolve dependency services for the performance's logic.
8+
All but one of these techniques (the last) provides full access to [the services which are added to the container].
349

35-
Developers are urged to consider encapsulating their performance logic in implementations of [`IHostsPerformance`].
36-
Through an overload (extension method) named [`ExecuteAsPerformanceAsync<T>`], developers may specify the concrete implementation of that interface.
37-
This extension method will resolve that implementation type along with any of its constructor-injected dependencies.
38-
This avoids the service locator anti-pattern and provides a convenient pattern by which to write performance logic.
10+
| Context | Technique |
11+
| ---------------------------------------------------- | -------------------------------------------------------- |
12+
| NUnit style test method | [Parameter inject into the test] method |
13+
| Reqnroll style binding class | [Constructor inject into the binding] class |
14+
| Standalone Screenplay: [`ExecuteAsPerformanceAsync`] | [Create a performance host, or use the service provider] |
15+
| Persona class | [Constructor inject into the Persona] class |
16+
| Performable class, such as a Task | [Use the actor's abilities] |
3917

40-
Use services resolved from the service provider, or injected into your [`IHostsPerformance`] implementation, to get access to [commonly-used Screenplay services] and anything else required at the root level of your performance logic.
41-
42-
[using Screenplay standalone]: ../gettingStarted/nonTesting/index.md
43-
[`Screenplay.ExecuteAsPerformanceAsync`]: xref:CSF.Screenplay.Screenplay.ExecuteAsPerformanceAsync(System.Func{System.IServiceProvider,System.Threading.CancellationToken,System.Threading.Tasks.Task{System.Nullable{System.Boolean}}},System.Collections.Generic.IList{CSF.Screenplay.Performances.IdentifierAndName},System.Threading.CancellationToken)
44-
[`IHostsPerformance`]: xref:CSF.Screenplay.IHostsPerformance
45-
[`ExecuteAsPerformanceAsync<T>`]: xref:CSF.Screenplay.ScreenplayExtensions.ExecuteAsPerformanceAsync``1(CSF.Screenplay.Screenplay,System.Collections.Generic.IList{CSF.Screenplay.Performances.IdentifierAndName},System.Threading.CancellationToken)
46-
47-
## Into personas
48-
49-
Types which derive from [`IPersona`] support constructor-injected dependencies.
50-
Personas are typically used by either [the cast] or [the stage] to get an [Actor].
51-
The technique in which they are used means that they are resolved, along with their constructor-injected dependencies, from DI.
52-
53-
Use constructor-injected dependencies in persona classes to provide access to the APIs required to resolve [Abilities] that the actor is to be granted.
54-
55-
[`IPersona`]: xref:CSF.Screenplay.IPersona
56-
[the cast]: xref:CSF.Screenplay.ICast
57-
[the stage]: xref:CSF.Screenplay.IStage
58-
[Actor]: xref:CSF.Screenplay.Actor
59-
[Abilities]: ../../glossary/Ability.md
60-
61-
## Into performables
62-
63-
_See the article explaining [how performables get their dependencies]_.
64-
65-
[how performables get their dependencies]: Performables.md
18+
[the services which are added to the container]: InjectableServices.md
19+
[Parameter inject into the test]: ParameterInjectionForTests.md
20+
[Constructor inject into the binding]: ConstructorInjectionForBindings.md
21+
[Create a performance host, or use the service provider]: InjectionForStandaloneScreenplay.md
22+
[Constructor inject into the Persona]: ConstructorInjectIntoThePersona.md
23+
[`ExecuteAsPerformanceAsync`]: xref:CSF.Screenplay.Screenplay.ExecuteAsPerformanceAsync(System.Func{System.IServiceProvider,System.Threading.CancellationToken,System.Threading.Tasks.Task{System.Nullable{System.Boolean}}},System.Collections.Generic.IList{CSF.Screenplay.Performances.IdentifierAndName},System.Threading.CancellationToken)
24+
[Use the actor's abilities]: Performables.md
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Dependency injection for standalone Screenplay
2+
3+
If you are [using Screenplay standalone] then the [`Screenplay.ExecuteAsPerformanceAsync`] permits resolution of dependencies via its parameter.
4+
That parameter is a `Func<IServiceProvider,CancellationToken,Task<bool?>>`.
5+
The service provider may be used to resolve dependency services for the performance's logic.
6+
7+
Developers are urged to consider encapsulating their performance logic in implementations of [`IHostsPerformance`].
8+
Through an overload (extension method) named [`ExecuteAsPerformanceAsync<T>`], developers may specify the concrete implementation of that interface.
9+
This extension method will resolve that implementation type along with any of its constructor-injected dependencies.
10+
This avoids the service locator anti-pattern and provides a convenient pattern by which to write performance logic.
11+
12+
Use services resolved from the service provider, or injected into your [`IHostsPerformance`] implementation, to get access to [commonly-used Screenplay services] and anything else required at the root level of your performance logic.
13+
14+
[using Screenplay standalone]: ../gettingStarted/nonTesting/index.md
15+
[`Screenplay.ExecuteAsPerformanceAsync`]: xref:CSF.Screenplay.Screenplay.ExecuteAsPerformanceAsync(System.Func{System.IServiceProvider,System.Threading.CancellationToken,System.Threading.Tasks.Task{System.Nullable{System.Boolean}}},System.Collections.Generic.IList{CSF.Screenplay.Performances.IdentifierAndName},System.Threading.CancellationToken)
16+
[`IHostsPerformance`]: xref:CSF.Screenplay.IHostsPerformance
17+
[`ExecuteAsPerformanceAsync<T>`]: xref:CSF.Screenplay.ScreenplayExtensions.ExecuteAsPerformanceAsync``1(CSF.Screenplay.Screenplay,System.Collections.Generic.IList{CSF.Screenplay.Performances.IdentifierAndName},System.Threading.CancellationToken)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Parameter injection for tests
2+
For testing frameworks which are based on **test methods** such as [NUnit], services are injected via _method parameter injection_. This is performed directly into each test method which is decorated with the `[Screenplay]` attribute.
3+
4+
[If Screenplay were to be extended] to work with frameworks such as xUnit or MSTest, then this same technique would be used.
5+
6+
Use dependencies injected in this way to get access to [commonly-used Screenplay services] and anything else required at the root level of your test logic.
7+
8+
[NUnit]: https://nunit.org/
9+
[If Screenplay were to be extended]: ../extendingScreenplay/TestIntegrations.md
10+
[commonly-used Screenplay services]: InjectableServices.md

0 commit comments

Comments
 (0)