AutoFac - Registering a decorator for some of an open Generic

后端 未结 2 1978
刺人心
刺人心 2021-01-13 14:19

I\'m attempting to set up an Autofac module that seems to have a complicated requirement.

here goes:

I have a generic interface:



        
2条回答
  •  日久生厌
    2021-01-13 15:00

    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
    

提交回复
热议问题