如何在可重用的Razor类库中的控制器中注入服务

时间:2018-10-21 00:30:32

标签: razor asp.net-core-mvc asp.net-core-2.1

我正在使用Razor类库来制作可在多个ASP.NET Core MVC项目中使用的可重用的复杂视图(包括其控制器和多个View组件)。问题是控制器使用依赖项注入(称为“ GatewayProxy”和字符串本地化的自定义服务)。将服务注入到RCL内部的控制器中的正确方法是什么?

这是我的RCL的结构:

enter image description here

这里是例外:

enter image description here

2 个答案:

答案 0 :(得分:4)

您提到了如何通过将依赖项添加到主项目的Startup.cs来解决此问题的方法。但是请注意,此可重用库的任何使用者可能都不记得(或不知道)您的库需要哪些依赖项。

解决此问题的方法是在您的Rcl中创建IServiceCollection的扩展名,以进行依赖项注册。

public static void AddMyRclServices(this IServiceCollection serviceCollection, IConfiguration config)
{
    serviceCollection.AddTransient<IRclService1, RclService1>();
    serviceCollection.AddScoped<IRclService2, RclService2>();
}

然后在Startup.cs中将您的MVC项目称为扩展名

using Rcl.Extensions

public void ConfigureServices(IServiceCollection services)
{
    services.AddMyRclServices(config);
}

答案 1 :(得分:1)

您可以从载荷装配中注入。 我的代码

ISturtupInitializers.cs

public interface ISturtupInitializers {
    void Compose(IServiceCollection serviceCollection);
}

TypeLoader.cs

public static readonly Lazy<HashSet<Assembly>> AllAssemblies = new Lazy<HashSet<Assembly>>(() => {
    var bin_folder = Assembly.GetExecutingAssembly().GetFileInfo().Directory.FullName;
    var bin_assembly_files = Directory.GetFiles(bin_folder, "*.dll", SearchOption.TopDirectoryOnly).Where(x => !SystemAssemblies.Any(xs => x.IndexOf(xs, StringComparison.CurrentCultureIgnoreCase) >= 0)).ToList();
    var assemblies = new HashSet<Assembly>();
    foreach (var a in bin_assembly_files)
    {
        try {
            var assName = AssemblyName.GetAssemblyName(a);
            var ass = Assembly.Load(assName);
            assemblies.Add(ass);
        } catch (SecurityException e) {
            //ignore
        } catch (FileNotFoundException e) {
            //ignore
        } catch (BadImageFormatException e) {
            //ignore
        }
        catch (Exception e) {
            throw;
        }
    }

    return assemblies;
});

public static string[] SystemAssemblies = new[] {
    "Microsoft.",
    "System.",
    "Newtonsoft."
};
public static FileInfo GetFileInfo(this Assembly assembly)
{
    var uri = new Uri(assembly.CodeBase);
    var path = uri.LocalPath;
    return new FileInfo(path);
}

Composer.cs

public class Composer {
    private static readonly Lazy<HashSet<Type>> _sturtup_initializers = new Lazy<HashSet<Type>>(() => {
        var aseemblies = TypeLoader.AllAssemblies.Value.SelectMany(x=>GetAllTypesInAssembly(x, typeof(ISturtupInitializers)));
        var result = new HashSet<Type>();
        foreach (var item in aseemblies) {
            result.Add(item);
        }

        return result;
    });

    public static void Compose(IServiceCollection services) {
        var composers = _sturtup_initializers.Value;

        foreach (var compose in composers) {
            public static void Compose(IServiceCollection services, IConfiguration configuration) {
        var composers = _sturtup_initializers.Value;

        var provider = services.BuildServiceProvider();

        foreach (var compose in composers) {
            ((IStartupInitializers) ActivatorUtilities.CreateInstance(provider, compose)).Compose(services, configuration);
        }
    }
        }
    }

    private static IEnumerable<Type> GetAllTypesInAssembly(Assembly assembly, Type implementInterface) {
        var types = assembly.GetTypes();
        return types.Where(x => x.GetInterfaces().Any(i => i == implementInterface));
    }
}

MyStartup.cs

public class ServiceCollectionExtensions : ISturtupInitializers
{
    public void Compose(IServiceCollection serviceCollection) {
        /** YOUR CODE **/
    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services) {
    /** YOUR CODE **/
    Composer.Compose(services);
}