I\'m attempting to set up an Autofac module that seems to have a complicated requirement.
here goes:
I have a generic interface:
Alright, I didn't realise the question was from 3 years ago as it was updated just a week ago.
We can take advantage of the chained methods during registration to segregate types that are decorated with the attribute from those that are not.
using System;
using System.Collections.Generic;
using System.Linq;
using Autofac;
namespace ConsoleApplication1
{
public interface IOpenGeneric
{
U Get(T value);
}
[AttributeUsage(AttributeTargets.Class)]
public class DecorateAttribute : Attribute
{
}
[Decorate]
public class BooleanToStringOne : IOpenGeneric
{
public string Get(bool value)
{
return $"{value.ToString()} from BooleanToStringOne";
}
}
[Decorate]
public class BooleanToStringTwo : IOpenGeneric
{
public string Get(bool value)
{
return $"{value.ToString()} from BooleanToStringTwo";
}
}
public class BooleanToStringThree : IOpenGeneric
{
public string Get(bool value)
{
return $"{value.ToString()} from BooleanToStringThree";
}
}
public class OpenGenericDecorator : IOpenGeneric
{
private readonly IOpenGeneric _inner;
public OpenGenericDecorator(IOpenGeneric inner)
{
_inner = inner;
}
public U Get(T value)
{
Console.WriteLine($"{_inner.GetType().Name} is being decorated!");
return _inner.Get(value);
}
}
public static class ReflectionExtensions
{
public static bool HasAttribute(this Type type)
where TAttribute : Attribute
{
return type
.GetCustomAttributes(typeof(TAttribute), false)
.Cast()
.Any();
}
}
class Program
{
static void Main(string[] args)
{
var assembly = typeof(Program).Assembly;
var builder = new ContainerBuilder();
// associate types that have the [Decorate] attribute with a specific key
builder
.RegisterAssemblyTypes(assembly)
.Where(x => x.HasAttribute())
.AsClosedTypesOf(typeof(IOpenGeneric<,>), "decoratable-service");
// get the keyed types and register the decorator
builder.RegisterGenericDecorator(
typeof(OpenGenericDecorator<,>),
typeof(IOpenGeneric<,>),
"decoratable-service");
// no key for the ones with no [Decorate] attribute so they'll
// get resolved "as is"
builder
.RegisterAssemblyTypes(assembly)
.Where(x => !x.HasAttribute())
.AsClosedTypesOf(typeof(IOpenGeneric<,>));
var container = builder.Build();
var booleanToStrings = container.Resolve>>();
foreach (var item in booleanToStrings)
{
Console.WriteLine(item.Get(true));
Console.WriteLine();
}
Console.ReadLine();
}
}
}
The output from the console is
BooleanToStringTwo is being decorated!
True from BooleanToStringTwo
BooleanToStringOne is being decorated!
True from BooleanToStringOne
True from BooleanToStringThree