【问题标题】:How to inject services in a controller inside a reusable Razor Class Library如何在可重用 Razor 类库中的控制器中注入服务
【发布时间】:2018-10-21 00:30:32
【问题描述】:

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

这是我的 RCL 的结构:

这是一个例外:

【问题讨论】:

  • 你是否在启动时向服务集合注册了依赖关系?
  • 我应该在RCL项目中还是在ASP.NET MVC项目中创建一个Startup.cs?
  • 主 MVC 项目。它应该已经有一个。在那里注册依赖项
  • @Nkosi 成功了。我设法创建了一个非常有前途的可重用 RCL。剩下的唯一问题是缺乏对像 javascript 这样的静态文件的支持。您知道将它们包含在我的 RCL 中的好方法吗?
  • @RenatoSanhueza:这应该是一个单独的问题,但通常,您必须将它们添加为嵌入式资源 (<ItemGroup><EmbeddedResource Include="wwwroot\**\*" /></ItemGroup>)。然后,您需要在使用此 RCL 获取它们的实际 Web 应用程序中添加嵌入式文件提供程序。见:docs.microsoft.com/en-us/aspnet/core/fundamentals/…

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


【解决方案1】:

您提到了如何通过将依赖项添加到主项目的 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);
}

【讨论】:

  • 我认为这是最好的方法,但并不完美,因为 RCL 的使用者仍然必须知道调用 services.AddMyRclServices(config)。我希望 RCL 有一个 Startup.cs。
  • @Tolga 你在 2.2 RCL 中找到了 startup.cs >
  • 您在哪里/如何将它包含在 RCL 和组件中?
  • 在 RCL 的某处创建一个公共静态类
【解决方案2】:

您可以从加载程序集中注入。 我的代码

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);
}

作曲家.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);
}

【讨论】:

    猜你喜欢
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多