Dotnetdi
Registering a Service
Constructor Injection
With constructor Injection we define the list of required dependencies as parameters of the constructor for the class
class IainsController : Controller
{
private IIainsWidget _iainsWidget;
public IainsController(IIainsWidget iainsWidet)
{
_iainsWidget = iainsWidget;
}
}
Registering a Service
In ASP Core the service must be registered with the IServiceCollection in the startup class configureServices.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IIainsWidget, IainsWidget>();
}
TryAdd
Adding the same interface twice will fail if you use the TryAdd whereas the without the service is added but not used. You can replace a service using the Replace method and the ServiceDescriptor.
Multiple Registeration for a Service
One use of this, registering a service with x number of implementations might be a set of rules. In the example provided the user created a rule processors.
public void ConfigureServices(IServiceCollection services)
{
services.Add<ICourtRule, ClubIsOpen>();
services.Add<ICourtRule, MaxBookingLength>();
services.Add<ICourtRule, MaxPeakTime>();
services.Add<ICourtRuleProcessor, CourtRuleProcessor>();
}
...
public class CourtRuleProcessor : ICourtRuleProcessor {
private readonly IEnumerable<ICourtRule> _rules;
public CourtRuleProcessor(IEnumerable<ICourtRule> rules) {
rules = _rules
}
public async Task<bool, IEnumerable<string>)> PassesAllRulesAsync(
...
}
Composite Services
Perhaps the original service sent only an email. By creating a composite class you can change this behaviour with no change to the controller by create a Notification service which registers two implementations.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<EmailService>();
services.AddSingleton<SmsService>();
services.AddSingleton<INotificationService>(serviceProvider => {
return new CompositeService(
new INotificationService[] {
serviceProvider.GetRequiredService<EmailService>,
serviceProvider.GetRequiredService<SmsService>
});
});
}
...
public class CourtRuleProcessor : ICourtRuleProcessor {
private readonly IEnumerable<ICourtRule> _rules;
public CourtRuleProcessor(IEnumerable<ICourtRule> rules) {
rules = _rules
}
public async Task<bool, IEnumerable<string>)> PassesAllRulesAsync(
...
}
Microsoft Dependency Injection Container
Introduction
When building a site try and build a dependency graph which will help determine what services you will need
Configuration
An options class:
- Must be non-abstract with a public parameterless constructor.
- All public read-write properties of the type are bound.
- Fields are not bound. In the preceding code, Position is not bound. The Position property is used so the string "Position" doesn't need to be hard coded in the app when binding the class to a configuration provider.
Example
public class PositionOptions
{
public const string Position = "Position";
public string Title { get; set; }
public string Name { get; set; }
}
Now this can be passed using Dependency Injection using the Startup
public void ConfigureServices(IServiceCollection services)
{
services.Configure<PositionOptions>(Configuration.GetSection(
PositionOptions.Position));
}
Add in the Controller
public void HomeController : Controller
{
private PostionalOptions _positionalOptions;
public HomeController(IOptions<PositionOptions> options)
{
_positionalOptions = options;
}
}
Service Lifetimes
These can be
- Transient, create each time they are requested
- Singleton once
- Scoped on demand (each request)