GithubHelp home page GithubHelp logo

flitbit / fbioc Goto Github PK

View Code? Open in Web Editor NEW
0.0 2.0 1.0 637 KB

FlitBit IoC - inversion of control container for dotNet that plays nicely with emitted types.

License: MIT License

C# 90.80% Puppet 0.03% Shell 3.78% PowerShell 5.39%

fbioc's Introduction

fbioc - FlitBit.IoC

An inversion of control container with constructor injection and synergy with dynamically emitted types.

Why

The FlitBit Frameworks rely heavily on meta-programming. In particular, several of the frameworks dynamically emit entire implementations at runtime from metadata, attributes, and descriptions of stereotypical behavior.

It was difficult hooking my prior favorite IoC in a satisfactory way for my [late-late-bound, dynamically emitted] needs. Many implementations are simply not available or predictable at startup time, which is when most IoC containers must be constructed and made whole (ie. everything registered).

Furthermore, I am of the opinion that an application's wireup activity (bootstrap) is a separate concern from inversion of control. I wanted an inversion of control container that was dynamic enough to be reconfigured throughout the life of an application, not just during the bootstrap, while still performing well in the object-creation cycle.

How

Inversion of control containers serve primarily as a mechanism to acquire constructed instances of replaceable implementations. This description [my own] implies that you go to the container for new instances rather than newing them up in code. Indeed, this is our strong recommendation. Toward that end, FlitBIt.IoC has a few helper classes that makes creating things feel natural and makes semantic sense.

var it = Create.New<WhatItIs>();

The above statement creates an instance of WhatItIs. WhatItIs may be any class, or any interface, provided that if it is abstract, a preferred implementation can be determined by the container.

In the vast majority of your code, this is the only call you'll make.

Inside Create.New<T>()

Create.New<T>() is a convenience [shortcut] that uses the ambient container to create the nearest registered implementation.

To visualize what it does, consider this code:

var container = Container.Current;
var it = container.New<WhatItIs>(LifespanTracking.External);

In the above code, the ambient container is accessed using the static Container.Current property. FlitBit.IoC supports nested container scopes. If the calling code doesn't create a child container then the ambient container corresponds to the Container.Root which is constructed and initialized at wireup time.

Nested Containers

An alternative to using Create.New<T>() would be to work within a child container like the following:

using(var create = Create.NewContainer())
{
  var it = create.New<WhatItIs>();

  // do something with it
}

By creating a child container, we establish a new container scope and the call to New<T>() now tracks the lifespan of the instance that it returns, ensuring that if it is-a IDisposable it's Dispose method is called when the child container is disposed. This lifespan tracking is convenient for many code patterns.

Child containers inherit the registrations of the outer container, and if new registrations are made on child containers those registrations are valid only within the scope of the child. This is what is meant by nearest.

Registering Implementations for Replaceable Types

Many of the FlitBit Frameworks register their own implementations with the IoC container. This is nearly always true of dynamically emitted implementations. However, user supplied types will need to be registered in user code. The recommended way to register an implementation is by either annotating it with a ContainerRegisteredAttribute or explictly adding it to the ambient container's registry.

The sections below will refer to these types:

public interface IBeNamed
{
  string Name { get; }
}

[ContainerRegister(typeof(IBeNamed), RegistrationBehaviors.Default)]
public class A : IBeNamed
{
	public A() { this.Name = this.GetType().Name; }
	public string Name { get; protected set; }
}

public class B : IBeNamed
{
	public B() { this.Name = this.GetType().Name; }
	public string Name { get; protected set; }
}

Implicit Registration via ContainerRegistered

If there is only one, default implementation of an abstract type, the type can be annotated with the ContainerRegisterAttribute like the class A in the example above. The wireup process will discover these attributes and automatically register those types with the root container. There is nothing more to do than use Create.New<IBeNamed>() when you need one.

Explicit Registration using the Registry

If you need to make a later decision about which implementation type will be registered, you can use explicit registration. For instance, the following code replaces the implicit registration of type A with type B:

Container.Root.Registry
  .ForType<IBeNamed>()
  .Register<B>()
  .End();

Following this explicit registration, calls to Create.New<IBeNamed>() will result in an instance of B instead of an instance of A.

More

So far I've only covered the most basic stuff.

// TODO: Add more documentation

I encourage you to take a look at the unit tests for much more insightful stuff about this IoC.

fbioc's People

Contributors

elimumford avatar megamaddu avatar

Watchers

James Cloos avatar  avatar

Forkers

tylergarlick

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.