.NET 8 Внедрение зависимостей с использованием отражения: служба с общим методом возвращающего задания <>C#

Место общения программистов C#
Ответить
Anonymous
 .NET 8 Внедрение зависимостей с использованием отражения: служба с общим методом возвращающего задания <>

Сообщение Anonymous »

Я хочу загрузить все типы из сборки и зарегистрировать их для инъекции зависимости, используя следующий метод, тяжелый отражение: < /p>
using System.Reflection;

namespace Server
{
public static class AddServices
{
public static IServiceCollection AddRepositories(this IServiceCollection services)
{
Assembly.Load("Services")
.GetTypes()
.Where(a => !a.IsAbstract && !a.IsInterface)
.Select(a => new { assignedType = a, serviceTypes = a.GetInterfaces() })
.ToList()
.ForEach(typeToRegister =>
{
if (typeToRegister.serviceTypes.Length != 1)
return;
services.AddScoped(typeToRegister.serviceTypes[0], typeToRegister.assignedType);
});
return services;
}
}
}
< /code>
Это гарантирует, что мне не нужно вручную регистрировать множество зависимостей (и вручную обновлять список каждый раз, когда я создаю новую зависимость). Это правда, что это не обрабатывает сценарий, в котором зависимость реализует несколько интерфейсов. Например, зависимостью, которая реализует как ирепозитория, так и idisposable, будет проигнорирована этим методом. Но не сложно добавить отрицатель интерфейсов, которые игнорируются этим методом (например, Idisposable). Мой код не имеет таких зависимостей, поэтому у него нет отрицателя.using Dto.Interfaces;

namespace Services
{
public interface IRepository
{
public Task Calculate(List list)
where T : ICommonProps;
}

public class Repository : IRepository
{
public async Task Calculate(List list)
where T : ICommonProps
{
//implementation irrelevant
await Task.Delay(100);
foreach (var thing in list)
{
Console.WriteLine(thing);
}
return 0m;
}
}
}
< /code>
Вдруг, что программа сбоятся во время запуска со следующим причудливым сообщением об ошибке: < /p>

не может создать экземпляры типа реализации
'dotneteightfeatureTesting.server.services.Repository+d__0`1t]'br /> for Service Type. 'System.runtime.compilerservices.iasyncstatemachine'. Вы можете легко обойти эту проблему, изменив код, чтобы не использовать задачи, но это совершенно непригодно для производственного API. .Where(a => !a.IsAbstract && !a.IsInterface && !a.IsGenericType)

Но это не подходит для любого, кто на самом деле имеет общие зависимости, зарегистрированные в их приложении. не хочу совета о том, как я мог изменить API. Это упрощенный пример, в котором отсутствуют все мои промежуточные программные слои. Кроме того, постарайтесь не заблудиться в сорняках, размышляя обо всех возможных сценариях инъекции зависимости; Сосредоточьтесь на наиболее распространенных. Он использует 3 проекта в одном решении, с именем сервера, служб и DTO. Структура папок может быть выведена из пространств имен. Серверные ссылки Услуги и DTO, и сервисы ссылки DTO. (Это требуется для минимального воспроизводимого примера, в противном случае метод AddRepositories найдет кучу дополнительного мусора.) < /P>
Программа: < /p>
using Server;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddRepositories()
.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
< /code>
dto.interfaces:
namespace Dto.Interfaces
{
public interface ICommonProps
{
long Id { get; }

string Name { get; }
}
}
< /code>
dto: < /p>
using Dto.Interfaces;

namespace Dto
{
public record Company(long Id, string Name, string TaxCode) : ICommonProps
{
public override string ToString() => $"{Id} {Name}: {TaxCode}";
}

public record Person(long Id, string Name, DateTimeOffset Birthday) : ICommonProps
{
public override string ToString() => $"{Id} {Name}: {Birthday}";
}
}
< /code>
контроллеры: < /p>
using Microsoft.AspNetCore.Mvc;
using Dto;
using Services;

namespace Server.Controllers
{
[ApiController]
[Route("[controller]")]
public class FlexibleController : ControllerBase
{
private readonly IRepository _repository;

public FlexibleController(IRepository repository)
{
_repository = repository;
}

[HttpPost(nameof(CalculateForPeople))]
public async Task CalculateForPeople([FromForm] List people)
{
return await _repository.Calculate(people);
}

[HttpPost(nameof(CalculateForCompanies))]
public async Task CalculateForCompanies([FromForm] List companies)
{
return await _repository.Calculate(companies);
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/797 ... hod-return
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»