Simple IoC container for Microsoft .NET
MiniAutFac was created in order to understand how reflection and original AutoFac work. It is not dedicated for complex projects (see http://code.google.com/p/autofac/ instead) - rather for educational purposes and simple solutions.
Features
- Simple code
- Lightweight (about 30 kb)
- Resolving constructors parameters
- Detecting circular dependencies (only throws exception)
- Attribute-based registration
- AutoFac-like lifetime scopes
- Proper instance registering when using predicate on assembly
- Additional parameters when resolving
- Open generic support
- Invlaid version on nuget, fix.
- Fixed small bug when resolving keyed services with IEnumerable.
- Validating type of instance factory result at resolve time (not while registering) when object is used as a return type
- Resolving services by a key
- Resolving Lazy - instances are resolved only when Value is called.
- Registering type via value factory
- Parameters (named and evaluted paramteres)
- Registering own instance factory for type
- Simple modules
- Fixed bug: when resolving enumerable within nested liftime scope and resolved instance was disposed incorrectly
- Fixed invalid assembly version inside nuget package.
- Fixed bug when resolving
IEnumerable
regstired per lifetime scope
- Removed registering from namespace (found it useless and not efficient)
- Registering multiple classes / types chosen with predicate within assemblies
- Registering multiple items
- First release
- Base features
var builder = new ContainerBuilder();
builder.Register<Foo>();
var resolver = builder.Build();
var fooInstance = resolver.Resolve<Foo>()
var builder = new ContainerBuilder();
builder.Register<Bar>().As<Foo>();
var resolver = builder.Build();
var fooInstance = resolver.Resolve<Foo>(); // fooInstance.GetType() == typeof(Bar)
public class Foo: IFoo {
}
...
var builder = new ContainerBuilder() { ResolveImplicit = true };
builder.Register<Foo>();
var resolver = builder.Build();
var fooInstance = resolver.Resolve<IFoo>(); // fooInstance.GetType() == typeof(Foo)
var builder = new ContainerBuilder();
builder.Register<Foo1>().As<IFoo>();
builder.Register<Foo2>().As<IFoo>();
IEnumerable<IFoo> fooInstances = builder.Build().Resolve<IEnumerable<IFoo>>();
[ContainerType(typeof(Bar))]
[ContainerType(typeof(IFoo))]
class Foo: Bar, IFoo
{
}
...
var builder = new ContainerBuilder();
builder.Register();
var container = builder.Build();
var instance1 = container.Resolve<Bar>();
var instance2 = container.Resolve<IFoo>();
var builder = new ContainerBuilder();
builder.Register<Foo>().AsImplementedInterfaces();
var cnt = builder.Build();
var instance = cnt.Resolve<IFoo>();
var bld = new ContainerBuilder();
bld.Register(type => typeof(IFoo).IsAssignableFrom(type),
Assembly.GetExecutingAssembly()).As<IFoo>();
var container = bld.Build();
var foos = container.Resolve<IEnumerable<IFoo>>();
After building container, you can create many nested lifetime scopes that manages a life cycle of registered instances.
var builder = new ContainerBuilder();
builder.Register<Foo>().PerLifetimeScope();
using (var container = builder.Build())
{
var foo = container.Resolve<Foo>();
var scope = container.BeginLifetimeScope();
var nextFoo = scope.Resolve<Foo>();
var anotherFoo = container.Resolve<Foo>();
// when container is disposed, it disposes also all child scopes
}
// references foo and anotherFoo are the same, but they are different to nextFoo
//(it was created in other scope).
Possible scopes so far:
SingleInstance
- single instance per container (shared among all nested lifetime scopes)PerDependency
- instance created everyResolve
requestPerLifetimeScope
- instance shared among single lifetime scope
You can tells the resolvable to to apply own buult instance as parameter, when resolving:
public class Foo
{
public Foo(string parameter1)
{
}
}
var builder = new ContainerBuilder();
builder.Register<Foo>()
.WithNamedParameter("paramter1", "value");
var cnt = builder.Build();
var fooInst = cnt.Resolve<Foo>();
You can create own instance factory for paramter:
var builder = new ContainerBuilder();
builder.Register<Foo>().WithEvalutedParameter(
"logger",
requesingType => new Logger(requestingType));
var foo = builder.Build().Resolve<Foo>();
bld.Register<Foo>().As(ctx =>
{
// some other methods
return new Logger(ctx.RequestingType);
// Requesting type is type, that request that instance
// when f.e. injected as construcot parameter. Can be null, if type
// resolved directly
}).PerLifetimeScope();
var bld = new ContainerBuilder();
var bInst = new ClassB();
bld.Register(context => bInst).As<InterfaceForClassB>();
var bld = new ContainerBuilder();
bld.Register(typeof(GenericClass<>)).As(typeof(IGenericClass<>));
var cnt = bld.Build();
var inst = cnt.Resolve<IGenericClass<string>>();
var bld = new ContainerBuilder();
bld.Register(typeof(SomeClass)).As(typeof(SomeClass));
var cnt = bld.Build();
var inst = cnt.Resolve<SomeClass>(new NamedParameter("SomeParam", someInstanceOfParameter));
var builder = new ContainerBuilder();
builder.Register<Bar>();
var cnt = builder.Build();
var result = cnt.Resolve<Lazy<Bar>>();
result.Value // that causes resolution in fact