我正在使用Razor类库来制作可在多个ASP.NET Core MVC项目中使用的可重用的复杂视图(包括其控制器和多个View组件)。问题是控制器使用依赖项注入(称为“ GatewayProxy”和字符串本地化的自定义服务)。将服务注入到RCL内部的控制器中的正确方法是什么?
这是我的RCL的结构:
这里是例外:
答案 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);
}