예제 #1
0
        private static void RegisterModulesDependencies(IServiceCollection services, LeafModulesOptions options)
        {
            // TODO: 어셈블리에서 디펜던시를 판단해서 등록하는 코드를 분리할 것
            var fileProvider = new PhysicalFileProvider(options.BasePath);

            var dllFiles = fileProvider.GetDirectoryContents("");

            if (!dllFiles.Exists)
            {
                return;
            }

            foreach (var dllFile in dllFiles
                     .Where(f => !f.IsDirectory && f.Exists &&
                            Path.GetExtension(f.Name).Equals(@".dll", StringComparison.OrdinalIgnoreCase)))
            {
                // TODO: try catch 처리
                var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(dllFile.PhysicalPath);

                var classes =
                    from type in assembly.GetTypes()
                    let attribute = type.GetCustomAttribute(typeof(DependencyServiceAttribute), true)
                                    where attribute != null
                                    select new { Type = type, Attribute = (DependencyServiceAttribute)attribute };

                foreach (var serviceClass in classes)
                {
                    if (serviceClass.Attribute.ImplemenType != null)
                    {
                        // TODO: ImplementType을 지정한 인터페이스를 구현한 클래스가 아닐 경우 예외를 발생시킬지 결정 - 예외 발생 시 시스템 스타트 오류 처리 필요
                        if (!serviceClass.Attribute.ImplemenType.IsAssignableFrom(serviceClass.Type))
                        {
                            continue;
                        }

                        // TODO: 지정한 인터페이스 형식으로 등록된 클래스가 있을 경우의 처리

                        if (serviceClass.Attribute.Singleton)
                        {
                            services.AddSingleton(serviceClass.Attribute.ImplemenType, serviceClass.Type);
                        }
                        else
                        {
                            services.AddTransient(serviceClass.Attribute.ImplemenType, serviceClass.Type);
                        }
                    }
                    else
                    {
                        if (serviceClass.Attribute.Singleton)
                        {
                            services.AddSingleton(serviceClass.Type);
                        }
                        else
                        {
                            services.AddTransient(serviceClass.Type);
                        }
                    }
                }
            }

            // TODO: Dll 파일의 변경이 있을 때 어플리케이션을 셧다운 - 재시작은 운영체제에 일임 (systemd 나 supervisord 이용)
            // https://www.blakepell.com/asp-net-core-ability-to-restart-your-site-programatically-updated-for-2-0
            // https://www.blakepell.com/asp-net-core-ability-to-restart-your-site-programmatically

            var token = fileProvider.Watch("**/*.dll");

            token.RegisterChangeCallback(state => { options.Shutdown?.Invoke(); }, null);
        }
예제 #2
0
 public static IServiceCollection AddLeafModules(this IServiceCollection services, LeafModulesOptions options)
 {
     if (options == null)
     {
         throw new ArgumentNullException(nameof(options));
     }
     RegisterModulesDependencies(services, options);
     return(services);
 }