-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial
- How can I use this library?
- Installation
- Service attributes
- Service configurator
- Scanning assemblies
Here are some of the ways you can use this little library:
-
Scanning assemblies for services - if your dependency injection requirements aren't too complex, allowing the usage of
IServiceCollectionfacade interface, and creating methods likeAddMvcfor you business logic is out of question because you use CI and use a plugin system to load your services, you can useServiceAttributeorIServiceConfiguratorclasses to scan your assemblies and load them into the service collection; -
IServiceConfiguratorto aggregate related registrations - if you wan't to put all related service registrations into a single bag, you can createIServiceConfiguratorimplementations and scan or manually add them into the services collection;
SimpleSoft's DependencyInjection can be installed via NuGet packages. Just run the following command in your project or search for it in Visual Studio NuGet package explorer:
Install-Package SimpleSoft.Extensions.DependencyInjectionThis library brings the ServiceAttribute that can be used to mark some class to be loaded as a service into the IServiceCollection. The following code represents an interface that will be used to log messages, and an implementation that outputs those messages into the command line:
public interface ILogger
{
void Log(string message);
}
public class Logger : ILogger, IDisposable
{
public void Log(string message)
{
Console.WriteLine(message);
}
public void Dispose()
{
// do nothing
}
}Lets list some service registration examples using the ServiceAttribute:
- Singleton service, only resolvable by its interfaces
[Service]
public class Logger : ILogger, IDisposable
{
\\ ...
}\\ equivalent code
serviceCollection.AddSingleton<ILogger, Logger>();
serviceCollection.AddSingleton<IDisposable, Logger>();- Transient service, only resolvable by specific interfaces
[Service(ServiceLifetime.Transient, TypesToRegister = new[] {typeof(ILogger)})]
public class Logger : ILogger, IDisposable
{
\\ ...
}\\ equivalent code
serviceCollection.AddTransient<ILogger, Logger>();- Scoped service, using
TryAddand resolvable by its interfaces and implementation
[Service(ServiceLifetime.Scoped, TryAdd = true, Registration = RegistrationType.All)]
public class Logger : ILogger, IDisposable
{
\\ ...
}\\ equivalent code
serviceCollection.TryAddScoped<ILogger, Logger>();
serviceCollection.TryAddScoped<IDisposable, Logger>();
serviceCollection.TryAddScoped<Logger>();This library brings the IServiceConfigurator interface that can be used to manually add services into the IServiceCollection, giving total registration control, but still allowing for assembly scan. The following code represents an interface that will be used to log messages, and an implementation that outputs those messages into the command line, based on a global logging options:
public interface ILogger
{
void Log(string message);
}
public class Logger : ILogger, IDisposable
{
private readonly LoggerOptions _options;
public Logger(LoggerOptions options)
{
_options = options;
}
public void Log(string message)
{
if (_options.Enabled)
Console.WriteLine(message);
}
public void Dispose()
{
// do nothing
}
}
public class LoggerOptions
{
public bool Enabled { get; set; }
}In this case, because we want to add all the implementations as services, but change the LoggerOptions.Enabled to true, an implementation of IServiceConfigurator will be created.
public class LoggerConfigurator : IServiceConfigurator
{
public void Configure(IServiceCollection services)
{
services
.AddSingleton<ILogger, Logger>()
.AddSingleton(k => new LoggerOptions
{
Enabled = true
});
}
}To help scanning assemblies for classes marked with the ServiceAttribute or implementing IServiceConfigurator interface, the library offers some extension methods for that. Because you can use both the attributes and configurators, the following code uses all the available options:
public interface ILogger
{
void Log(string message);
}
[Service(TypesToRegister = new[] {typeof(ILogger)})]
public class Logger : ILogger, IDisposable
{
private readonly LoggerOptions _options;
public Logger(LoggerOptions options)
{
_options = options;
}
public void Log(string message)
{
if (_options.Enabled)
Console.WriteLine(message);
}
public void Dispose()
{
// do nothing
}
}
public class LoggerOptions
{
public bool Enabled { get; set; }
}
public class LoggerConfigurator : IServiceConfigurator
{
public void Configure(IServiceCollection services)
{
services.AddSingleton(k => new LoggerOptions
{
Enabled = true
});
}
}To scan the assembly and register everything into the IServiceCollection, one could use the following code:
var provider =
new ServiceCollection()
.AddServicesFrom(typeof(Logger).GetTypeInfo().Assembly)
.BuildServiceProvider();