Giter Site home page Giter Site logo

minioc's Introduction

MinIoC

MinIoC is a single-file, minimal C# IoC container. While there are several great IoC solutions available which are much more powerful and flexible, MinIoC aims to enable lightweight/small-footprint projects with a simple implementation. It is distributed as a single .cs file which can be included and compiled in other projects.

Build status

Example

var container = new Container();

container.Register<IFoo>(typeof(Foo));
container.Register<IBar>(() => new Bar());
container.Register<IBaz>(typeof(Baz)).AsSingleton();

/* ... */

var baz = container.Resolve<IBaz>();

The example above calls the generic Register<T>(Type) and Register<T>(Func<T>) methods. The first one binds the generic parameter type to an actual type, the second binds the generic parameter type to a factory function. Calling Resolve<T>() creates an instance of the registered type.

For a type binding, the container uses the actual type's first constructor. All arguments need to also be resolvable by the container.

API Details

The container implements IServiceProvider, exposing an object GetService(Type type) method and two non-generic registration methods: Register(Type @interface, Func<object> factory) and Register(Type @interface, Type implementation).

Generic extension methods are provided both for registration (Register<T>(Type), Register<T>(Func<T>), Register<T>()) and resolution (T Resolve<T>()).

Lifetimes

By default, each call to Resolve<T>() creates a new instance. Two other object lifetimes are supported: singleton and per-scope.

A singleton is created by calling AsSingleton() after registration:

container.Register<IFoo>(typeof(Foo)).AsSingleton();

var instance1 = container.Resolve<IFoo>();
var instance2 = container.Resolve<IFoo>();

Assert.AreEqual(instance1, instance2);

Scopes allow finer-grained lifetime control, where all types registered as per-scope are unique within a given scope. This allows singleton-like behavior within a scope but multiple object instances can be created across scopes. Scopes are created by calling CreateScope() on a contianer instance and they also implement IServiceProvider, exposing an object GetService(Type type) method (and a Resolve<T>() extension method):

container.Register<IFoo>(typeof(Foo)).PerScope();
  
var instance1 = container.Resolve<IFoo>();
var instance2 = container.Resolve<IFoo>();

// Container is itself a scope
Assert.AreEqual(instance1, instance2);

using (var scope = container.CreateScope())
{
    var instance3 = scope.Resolve<IFoo>();
    var instance4 = scope.Resolve<IFoo>();

    // Instances should be equal inside a scope
    Assert.AreEqual(instance3, instance4);
    
    // Instances should not be equal across scopes
    Assert.AreNotEqual(instance1, instance3);
}

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

minioc's People

Contributors

davidmatson avatar microsoft-github-policy-service[bot] avatar microsoftopensource avatar msftgits avatar vladris avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

minioc's Issues

Consider non-generic methods/IServiceProvider

Internally, I believe Container has everything as Type and object. Suppose a caller has a list of types to register and/or resolve, like this:

Type[] typesToRegister = new Type { typeof(A), typeof(B) };

foreach (Type toRegister in typesToRegister)
{
    container.Register(toRegister, toRegister);
}

Currently, I believe the caller would be required to use reflection to MakeGenericMethod. What's the ideal "Min" version of the container surface area? Perhaps:

IRegisteredType Register(Type interfaceType, Type implementationType);
IRegisteredType Register(Type interfaceType, Func<object> factory);

And for resolve:

object Resolve(Type interfaceType);

Does that feel like the right "Min" set? Extension methods could be built on top to support:

Register<T>(Type type); // current form
Register<T, TImplementation>(); // generic version for the second argument
Register(Type type); // class without a separate interface
Register<T>(); // generic version of above form
Register<T>(Func<T> factory); // current form
T Resolve<T>(); // current form

Thoughts?

Enable instantiable container

There are scenarios where we would want to spin up multiple container instances (eg. registering different types against each instance).

Started exploration of this here: https://github.com/Microsoft/MinIoC/tree/container_instances

Questions to explore:
Keep static Container API or remove in favor of always requiring instantiation or provide a static singleton on the instantiable type?
If we keep static Container, what's a good name for the new type?
Would we want a singleton that is a single instance across containers, or would a singleton only be unique for a container?
Should instantiable container implement IScope?
Is there any fundamental difference anymore between a scope and a container?

IDisposable on Scope doesn't call Dispose on cached instances

Based on reading the code; haven't tested, but I think the repro would be something like:

class SpyDisposable : IDisposable
{
    public bool Disposed { get; private set; }

    public void Dispose()
    {
        Disposed = true;
    }
}

Container.Register<SpyDisposable>(typeof(SpyDisposable));
SpyDisposable spy;

using (var scope = Container.CreateScope())
{
    spy = scope.Resolve<SpyDisposable>();
}

Assert.True(spy.Disposed);

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.