Skip to content

Instantly share code, notes, and snippets.

@mikeminutillo
Created September 18, 2012 07:55
Show Gist options
  • Save mikeminutillo/3741884 to your computer and use it in GitHub Desktop.
Save mikeminutillo/3741884 to your computer and use it in GitHub Desktop.
Arbitrary Attachments on Arbitrary Objects
interface IHaveAttachments { }
interface IAttachment<T> where T : IHaveAttachments {
void AttachTo(T obj);
}
class AttachmentsModule : Autofac.Module
{
private static readonly MethodInfo _attach = typeof(AttachmentsModule).GetMethod("Attach", BindingFlags.Static | BindingFlags.NonPublic);
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(ThisAssembly)
.AsClosedTypesOf(typeof(IAttachment<>))
.InstancePerDependency();
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
registration.Activating += Activating;
}
private static void Activating(object sender, ActivatingEventArgs<object> e)
{
if(e.Instance is IHaveAttachments)
CallAttach(e.Instance.GetType(), e.Instance, e.Context);
}
private static void CallAttach(Type t, object o, IComponentContext ctx)
{
_attach.MakeGenericMethod(t).Invoke(null, new[] { o, ctx });
}
private static void Attach<T>(T target, IComponentContext ctx) where T : IHaveAttachments
{
foreach(var attachment in ctx.Resolve<IEnumerable<IAttachment<T>>>())
attachment.AttachTo(target);
}
}
class ViewModel : IHaveAttachments { }
class MySampleViewModel : ViewModel
{
public int Foo { get; set; }
public string Bar { get; set; }
}
class FooAttachment : IAttachment<MySampleViewModel>, IHaveAttachments
{
public int Baz { get; set; }
public void AttachTo(MySampleViewModel obj)
{
obj.Foo = Baz;
}
}
class MeowAttachment : IAttachment<MySampleViewModel>
{
public void AttachTo(MySampleViewModel obj)
{
obj.Bar = "This is another attachment";
}
}
class OnAttachments : IAttachment<FooAttachment>
{
public void AttachTo(FooAttachment obj)
{
obj.Baz = 16;
}
}
class ViewModelModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(ThisAssembly)
.AssignableTo<ViewModel>()
.AsSelf()
.InstancePerDependency();
}
}
void Main()
{
var builder = new ContainerBuilder();
builder.RegisterModule<ViewModelModule>();
builder.RegisterModule<AttachmentsModule>();
var container = builder.Build();
var resolved = container.Resolve<MySampleViewModel>();
// resolved.Foo should be 16
// resolved.Bar should be "This is another attachment"
resolved.Dump();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment