Tuesday, January 25, 2011

Autofac Part 4 - ContainerBuilder: Advanced

ContainerBuilder - Advanced
Much more than the basic features, explained in Autofac - Part 1, can be done with Autofac.
This post will try to highlight some of them.

Choosing the constructor
Sometimes you are interested in using a specific constructor when resolving a type.
class TwoCtors
{
  public Type[] CalledCtor { get; private set; }

  public TwoCtors(A1 a1)
  {
    CalledCtor = new[] { typeof(A1) };
  }

  public TwoCtors(A1 a1, A2 a2)
  {
    CalledCtor = new[] { typeof(A1), typeof(A2) };
  }
}

public void ResolveWithTwoCtors()
{
  var cb = new ContainerBuilder();
  cb.RegisterType<A1>();
  cb.RegisterType<A2>();
  cb.RegisterType<TwoCtors>().UsingConstructor(selected)
}

There are also another option for choosing constructors, which is using named parameters.
class WithParam
{
  public int I { get; private set; }
  public WithParam(int i, int j) { I = i + j; }
}

public void ResolveWithParams()
{
  var ival = 10;
  var cb = new ContainerBuilder();
  cb.RegisterType<WithParam>()
    .WithParameter(new NamedParameter("i", ival))
    .WithParameter(new NamedParameter("j", ival));
}

Property Injection
Another feature of Autofac is property injection. Which basically means properties are set when an instance are created. There are several ways to do this.

Object initalizer which actually isn't a Autofac feature, but a .NET feature.
builder.Register(c => new A { B = "test" });
Or more advanced
builder.Register(c => new A { B = c.Resolve<B>() });

Using an activated event handler, which supports circular dependencies
builder.Register(c => new A()).OnActivated(e => e.Instance.B = "test");
Or more advanced
builder.Register(c => new A()).OnActivated(e => e.Instance.B = e.Context.Resolve<B>());

And last but not least, property autowiring.
class A
{
  public Val { get; set; }
}
var builder = new ContainerBuilder();
var val = "test";
builder.RegisterInstance(val);
builder.RegisterType<A>().PropertiesAutowired();
var container = builder.Build();
containter.Resolve<A>();

Collection registration
The last feature that will be touched in this post is collection registration.
var builder = new ContainerBuilder();
var cname = "s";
builder.RegisterCollection<string>(cname)
       .As<IEnumerable<string>>();
var s1 = "hello";
var s2 = "world";
builder.RegisterInstance(s1).MemberOf(cname);
builder.RegisterInstance(s2).MemberOf(cname);
var container = builder.Build();
container.Resolve<IEnumerable<string>>();

1 comment:

  1. You have an error on the 3rd line of the second to last example:

    "public Val { get; set; }"
    the type is missing

    ReplyDelete