避免通过依赖注入注册每一个服务

adv*_*api 1 .net c# dependency-injection

我有一个应用程序,其中有很多通过 DI 注册的服务,我想知道是否有以这种方式注册的最佳方法

      services.AddScoped<IDestinationService, DestinationService>();
        services.AddScoped<IAttractionService, AttractionService>();
        services.AddScoped<ICartService, CartService>();
        services.AddScoped<IPersonalService, PersonalService>();
        services.AddScoped<IUserService, UserService>();
        services.AddScoped<IEncryptionHelper, EncryptionHelper>();
        services.AddScoped<IAddressService, AddressService>();
        services.AddScoped<IUserRegistrationService, UserRegistrationService>();
        services.AddScoped<IUserRoleService, UserRoleService>();
        services.AddScoped<IEmailSender, EmailSender>();
        services.AddScoped<IUserRolesService, UserRolesService>();
        services.AddScoped<IProductAvailabilityService, ProductAvailabilityService>();
Run Code Online (Sandbox Code Playgroud)

我想过创建一个属性并将其放入类中,但我不知道这是否是一个好的做法..有什么建议吗?

nbo*_*ans 5

是的,我认为标记要由 DI 容器注册的类的属性是一个很好的解决方案。这就是我在自己的项目中所做的。

我创建了一个像这样的属性:

using Microsoft.Extensions.DependencyInjection;

[AttributeUsage(
    AttributeTargets.Class,
    AllowMultiple = false,
    Inherited = true)]
public sealed class DiClassAttribute : Attribute
{
    public ServiceLifetime Lifetime { get; internal set; }

    public DiClassAttribute(
        ServiceLifetime lifetime = ServiceLifetime.Scoped)
    {
        Lifetime = lifetime;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我用它来标记我的 DI 服务,如下所示(我使用抽象基类,不必向每个类添加属性):

[DiClass]
public abstract class BaseService
{
    // Rest of class...
}
Run Code Online (Sandbox Code Playgroud)

我定义了一个自定义扩展方法,用于IServiceCollection自动将所有标记的类添加到 DI 容器:

    public static IServiceCollection AddCustomServices(
        this IServiceCollection services)
    {
        var types = Assembly
            .GetExecutingAssembly()
            .GetTypes()
            .Where(t => !t.IsAbstract
                && t.GetCustomAttribute<DiClassAttribute>() != null)
            .ToArray();

        foreach (var type in types)
        {
            var attribute = type.GetCustomAttribute<DiClassAttribute>()!;
            var lifetime = attribute.Lifetime;

            var interfaces = type.GetInterfaces();

            foreach (var i in interfaces)
            {
                services.TryAdd(new ServiceDescriptor(i, type, lifetime));
            }

            if (!interfaces.Any())
            {
                services.TryAdd(new ServiceDescriptor(type, type, lifetime));
            }
        }

        return services;
    }
Run Code Online (Sandbox Code Playgroud)

我在我的中这样称呼它Program.cs

builder.Services.AddCustomServices();
Run Code Online (Sandbox Code Playgroud)

对我来说效果很好。