Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way of registering decorators by conventions? #22

Open
Rookian opened this issue May 11, 2015 · 1 comment
Open

Is there a way of registering decorators by conventions? #22

Rookian opened this issue May 11, 2015 · 1 comment

Comments

@Rookian
Copy link

Rookian commented May 11, 2015

With SimpleInjector or StructureMap you have the possibility to register decorators by conventions.

Registration with SimpleInjector:
container.RegisterDecorator(typeof(ICommandHandler<>),typeof(ValidationCommandHandlerDecorator<>));

For now I did not find a way of registering decorators by convention in Ninject.
Is there a way of doing this?

@Rookian
Copy link
Author

Rookian commented Jun 3, 2015

public static class KernelExtensions
{
    /// <summary>
    /// Binds an open generic type to its implementation and adds all its defined decorators
    /// </summary>
    /// <param name="kernel">Ninject Container</param>
    /// <param name="openGenericType">Open generic Type</param>
    /// <param name="assembly">Assembly to scan for the open generic type implementation</param>
    /// <param name="decoratorTypes">Types of the decorators. Order matters. Order is from the most outer decorator to the inner decorator</param>
    public static void BindManyOpenGenericsWithDecorators(this IKernel kernel, Type openGenericType, Assembly assembly, params Type[] decoratorTypes)
    {
        var allImplementations = GetAllTypesImplementingOpenGenericType(openGenericType, assembly);

        foreach (var type in allImplementations.Where(type => !decoratorTypes.Contains(type)))
        {
            var genericInterface = type.GetInterfaces().FirstOrDefault(x => openGenericType.IsAssignableFrom(x.GetGenericTypeDefinition()));

            // real implementation
            var parentType = decoratorTypes.Last();
            kernel.Bind(genericInterface).To(type)
            .WhenInjectedInto(parentType);
        }

        for (var i = 0; i <= decoratorTypes.Count() - 1; i++)
        {
            var decoratorType = decoratorTypes[i];

            if (i == 0)
            {
                // most outer decorator
                kernel.Bind(openGenericType).To(decoratorType);
            }
            else
            {
                // inner decorators
                var parentType = decoratorTypes[i - 1];
                kernel.Bind(openGenericType).To(decoratorType)
                    .WhenInjectedInto(parentType);
            }
        }
    }

    private static IEnumerable<Type> GetAllTypesImplementingOpenGenericType(Type openGenericType, Assembly assembly)
    {
        return (from type in assembly.GetTypes()
                from interfaceType in type.GetInterfaces()
                let baseType = type.BaseType
                where
                (baseType != null && baseType.IsGenericType &&
                openGenericType.IsAssignableFrom(baseType.GetGenericTypeDefinition())) ||
                (interfaceType.IsGenericType &&
                openGenericType.IsAssignableFrom(interfaceType.GetGenericTypeDefinition()))
                select type);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant