/photosphere-di

No longer supported | Simple .NET dependency injection framework based on emitting IL code at service registration time

Primary LanguageC#MIT LicenseMIT

Photosphere.DependencyInjection

Simple .NET dependency injection framework based on emitting IL code at service registration time.

Status

Windows build Status NuGet license

Install via NuGet

PM> Install-Package Photosphere.DependencyInjection

Features

Fast resolving

This container based on building dynamic methods (using System.Reflection.Emit) for every registered service. It is very speeds up the resolving of dependencies when requested.

Preferred declarative style

Container must be configured in a composition root of project/assembly.

internal class CompositionRoot : ICompositionRoot
{
  public void Compose(IRegistrator registrator)
  {
    registrator
      .Register<IFoo>()
      .Register<IBar>();
  }
}

You can hint composition root type for more faster container initialization

[assembly: CompositionRoot(typeof(FooCompositionRoot))]

Light container setup directly into attributes (instead CompositionRoot)

[assembly: RegisterDependencies(typeof(IService))]
[assembly: RegisterDependencies(typeof(IFoo), Lifetime.AlwaysNew)]

These methods of registration are resolved as follows:

  • at the first container try to search CompositionRootAttribute and use it;
  • if it wasn't founded, container try to get up registration info from RegisterDependenciesAttribute and RegisterDependenciesByAttribute;
  • if these attributes wasn't founded the whole-types-search for ICompositionRoot implementations will be performed.

Facilitate low coupling

Service can be registered just by interface: search of implementation is carried out in the registration process. It reduce horrible registration mappings that bring only redundant references through a code.
Just use Register<TService> method:

registrator.Register<IFoo>();
registrator.Register<IBar>();

for register implementations of IFoo and IBar.

Registering all descendants by common interface

interface IService {}
interface IFoo : IService{}
class Foo : IFoo {}
interface IBar : IService {}
class Bar : IBar
{
  public Bar(IFoo foo) {}
}
registrator.Register<IService>();
var foo = registrator.GetInstance<IFoo>();
var bar = registrator.GetInstance<Bar>();

Type registration by attribute on base type

If you don't want to register by interface or base type you can use your own custom attribute for it.

class ServiceAttribute : Attribute {}
[Service]
class Foo {}

class Bar : Foo {}

Registration

registrator.RegisterBy<ServiceAttribute>();

or

[assembly: RegisterDependenciesBy(typeof(ServiceAttribute))]

Providing

var foo = container.GetInstance<Foo>();
var bar = container.GetInstance<Bar>();

This attribute can be applyed to interfaces too.

Object graph analysis performed at registration time

Detects and denies cycles and not registered dependencies while service registration.

Cycle example

class Foo { public Foo(Bar bar) {} }
class Bar { public Bar(Buz buz) {} }
class Buz { public Buz(Foo foo) {} }

Control over objects life

Provides three strategies of managing of lifetime: services can be always created anew, lives only during the time of the request or has container bounded life. Not uber feature :)

Easy to use

Register:

internal class CompositionRoot : ICompositionRoot
{
  public void Compose(IRegistrator registrator)
  {
    registrator
      .Register<IFoo>()
      .Register<IBar>(Lifetime.AlwaysNew)
      .Register<IBuz>(Lifetime.PerRequest)
      .Register<IQiz>(Lifetime.PerContainer);
  }
}

...and resolve:

var container = new DependencyContainer();
var foo = container.GetInstance<IFoo>();
foo.DoSomething();

Collections injecting

var foos = container.GetInstance<IEnumerable<IFoo>>();

or

var foos = container.GetAllInstances<IFoo>();

or

class Bar
{
  public Bar(IEnumerable<IFoo> foos) {}
}

Instead IEnumerable can be used IReadOnlyCollection that can be preffered for more clean OOP style.

Generic registration

You can register generic service

registrator.Register(typeof(IGenericService<>))

and receive constructed type

var foo = container.GetInstance<IGenericService<IFoo>>();

or receive multiple constructed type

var bars = container.GetAllInstances<IGenericService<Bar>>();

Integrations