.NET Core Dependency Injection by Naming Convention

From Logic Wiki
Revision as of 10:48, 28 March 2018 by AliIybar (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


In order to automatically define dependencies in Core application, here is a trick using reflection.

in configuration I add Singleton with parameters as usual and call extension method

        private void ConfigureIoC(IServiceCollection services)
        {
            var conn = Configuration["ConnectionString"];
            var StaffDirectoryUrl = Configuration["StaffDirectoryApiUrl"];
            services.AddSingleton<ISmtpSettings>(new SmtpSettings(Configuration["SmtpSettings:Server"],
                int.Parse(Configuration["SmtpSettings:Port"]),
                Configuration["SmtpSettings:AuthType"],
                Configuration["SmtpSettings:Username"],
                Configuration["SmtpSettings:Password"],
                Configuration["SmtpSettings:FromAddress"],
                Configuration["SmtpSettings:FromName"]
            ));
            services.AddSingleton<IRepository>(new Repository.Repository(conn));
            services.AddSingleton<IAdService>(new AdService(StaffDirectoryUrl));
..........
            var assembly = System.Reflection.Assembly.GetExecutingAssembly();  //typeof().Assembly;
            services.AddTransientByConvention(assembly, x => x.Name.EndsWith("Service"));
            services.AddTransientByConvention(assembly, x => x.Name.EndsWith("Manager"));
            services.AddTransientByConvention(assembly, x => x.Name.EndsWith("Repository"));

And the extension method is :

    public static class ext
    {
        public static IServiceCollection AddTransientByConvention(this IServiceCollection services, Assembly assembly,
            Func<Type, bool> interfacePredicate, Func<Type, bool> implementationPredicate)
        {
            var interfaces = assembly.ExportedTypes
                .Where(x => x.IsInterface && interfacePredicate(x))
                .ToList();
            var implementations = assembly.ExportedTypes
                .Where(x => !x.IsInterface && !x.IsAbstract && implementationPredicate(x))
                .ToList();
            foreach (var @interface in interfaces)
            {
                if (!(services.Count(x => x.ServiceType.Name.EndsWith(@interface.Name) && x.Lifetime == ServiceLifetime.Singleton) > 0))
                {
                    var implementation = implementations.FirstOrDefault(x => @interface.IsAssignableFrom(x));
                    if (implementation == null) continue;
                        services.AddTransient(@interface, implementation);
                }
            }
            return services;
        }
        public static IServiceCollection AddTransientByConvention(this IServiceCollection services, Assembly assembly, Func<Type, bool> predicate)
            => services.AddTransientByConvention(assembly, predicate, predicate);
    }

Line 14 is to eliminate singleton classes I defined manually.