Skip to content

Tutorial

João Simões edited this page Oct 24, 2016 · 8 revisions

Content

How can I use this library?

Here are some of the ways you can use this little library:

  1. Scanning assemblies for services - if your dependency injection requirements aren't too complex, allowing the usage of IServiceCollection facade interface, and creating methods like AddMvc for you business logic is out of question because you use CI and use a plugin system to load your services, you can use ServiceAttribute or IServiceConfigurator classes to scan your assemblies and load them into the service collection;
  2. IServiceConfigurator to aggregate related registrations - if you wan't to put all related service registrations into a single bag, you can create IServiceConfigurator implementations and scan or manually add them into the services collection;

Installation

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.DependencyInjection

Service attributes

This 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 TryAdd and 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>();

Service configurator

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
			});
	}
}

Scanning assemblies

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();

Clone this wiki locally