Skip to content
This repository has been archived by the owner on Nov 2, 2018. It is now read-only.

DI Notes

Stephen Halter edited this page Mar 3, 2014 · 1 revision

IEnumerable is used to create ServiceProvider

  • add utility method to make fallback IServiceProvider - this will be called by fwks when their services are not present in the app container.
  • IServiceProvider static FooStatic.CreateProvider(IEnumerable<IServiceDescriptor> services)
  • ServiceProvider becomes immutable - copies service
  • ServiceProvider becomes internal - appearing only as IServiceProvider and IDisposable

public class ServiceDescriptor implementing IServiceDescriptor added to DI library

  • add utility method to make IServiceDescriptor
  • see Hosting example for using configuration to replace implemenationtType.
  • IServiceDescriptor static FooStatic.DescribeService(IConfiguration configuration, Type serviceType, Type implementationType, LifecycleKind lifecycle)
  • add bool AllowMultiple to IServiceDescriptor - this will be used in the fallback Create method, and the other container Populate methods
  • if any descriptors for a ServiceType have AllowMultiple false, apply only the last one in the group
  • both Create and Populate should put the services in to a GroupBy based on ServiceType

add utility method to Populate third-party containers

  • this populates and duck-punches the adjustments for required behaviors.
  • void static NinjectFooStatic.Configure(IEnumerable<IServiceDescriptor> services, AnotherContainerEgNinject container)
  • Each container type will have it's own project, which references the DI and an actual container, and adds that Configure

define assembly neutral IServiceScopeFactory interface with single IServiceProvider Create() method

  • also establish the service typeof(Func)
  • Invoke method is equivalent to typeof(IServiceScopeFactory) Create method

a service scope is virtually identical to a service provider.

  • it is also idisposable,
  • is also immutable,
  • is also internal,
  • it references the same body of services,
  • it holds a collection of non-transients that were resolved before,
  • it holds a collection of disposables that were resolved before

resolving a LifecycleKind.Transient from a service provider or service scope

  • creates a new instance each time
  • if the new instance implements idisposable, it is added to the collection of idisposables
  • the collection of disposables can be a weak reference

resolving a LifecycleKind.Scoped from a service provider or service scope

  • looks to see if a non-transient of the same service was resolved before
  • returns same instance if present
  • creates a new instance if not present, and adds to list of non-transients
  • if the new instance implements idisposable, it is added to the collection of idisposables

resolving a LifecycleKind.Singleton from a service provider or service scope

  • if there is no parent scope/container, use exactly the same rules as LifecycleKind.Scoped
  • if there is a parent call that parent and return the result
  • things coming from parent are not put into instance or disposable - that's the parent's job.

chaining containers

  • Build and Populate also accept chained container
  • IServiceProvider static Create(IEnumerable<IServiceDescriptor> services, IServiceProvider outer)
  • void static Populate(AnotherContainerEgNinject container, IEnumerable<IServiceDescriptor> services, IServiceProvider outer)

chained services

  • when a container is asked for a service it does not provide and the outer IServiceProvider is not null, call outer.GetService(serviceType) and return that if provided
  • do not add to non-transient or disposable lists - that is the outer container's job

scopes and chaining

  • a service scope is created and the parent has an outer IServiceProvider
  • if the outer IServiceProvider provides IServiceScopeFactory, then the new service scope should call that to get an outer container scope
  • if the returned outer container scope implements idisposable, add it to the list of weak disposable references
  • when the service scope is asked for a service that is not defined, it calls to the outer container scope
  • else if the outer IServiceProvider does not return Func, then the new service scope uses the outer container as it's outer container scope. It is not added to the list of disposables

disposing

  • when a service container or scope is disposed it should dispose everything in its weak reference list of idisposable instances it made

meta services- IEnumerable and open generics are meta services.

  • meta service is anything where the serviceType is not explicitly registered

IEnumerable - list of service typeof(T)

  • if there are any serviceType T registered, resolve and return them as an array
  • else if there is an outer container, pass the GetService IEnumerable to it
  • else return an empty

ISomething<> as Something<> - open generic services

if request for a closed generic serviceType typeof(ISomething) matches an open generic serviceType definition typeof(ISomething<>) then the corresponding open generic implementationType typeof(Something<>) is closed into implementationType typeof(Something) and the resulting closed serviceType and implementationType are used to resolve as if it was registered normally all of the other things about lifecyclekind and disposable apply