Служба веб-API — развязность с динамическими конечными точкамиC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Служба веб-API — развязность с динамическими конечными точками

Сообщение Anonymous »

Я играю с C# Web API (.net 8), выполняя базовый веб-сервис CRUD.
Я хочу отделить сервис от кода program.cs, например, если в будущем я захочу добавьте новую конечную точку в мой ItemsService.cs, я хочу, чтобы она стала конечной точкой без каких-либо других изменений в каких-либо других файлах, я реализовал это без контроллера с отражением.
это работает нормально, но затем я хотел добавить swaggerUI и Судя по тому, что я вижу, это вообще не работает с этими динамическими конечными точками, поэтому я подумал, может быть, мой подход считается «неправильным» или «не лучшей практикой»? есть ли что-нибудь вокруг? для меня нет смысла вносить изменения как в itemsService.cs, так и в контроллер/программу.cs при добавлении новой конечной точки, я ошибаюсь?
itemService.cs
public interface IItemService
{
Task GetById(int id);
Task Add(Item item);
Task Update(int id, Item item);
Task Delete(int id);
Task Search(string query);
}

public class ItemService : IItemService
{
private readonly MongoDbContext _context;
private readonly ElasticsearchClient _elasticClient;

public ItemService(MongoDbContext context, ElasticClientProvider elasticClientProvider)
{
_context = context;
_elasticClient = elasticClientProvider.Client;
}

[Endpoint("/items/{id:int}", "GET")]
public async Task GetById(int id)
{
Console.WriteLine($"GetById {id}");
return await _context.Items.Find(p => p.Id == id).FirstOrDefaultAsync();
}

[Endpoint("/items", "POST")]
public async Task Add(Item item)
{
//todo
}


EndpointAttribute.cs:
[AttributeUsage(AttributeTargets.Method)]
public class EndpointAttribute : Attribute
{
public string Route { get; }
public string HttpMethod { get; }

public EndpointAttribute(string route, string httpMethod = "GET")
{
Route = route;
HttpMethod = httpMethod;
}
}

program.cs:
using BasicServer.DAL;
using BasicServer.DAL.Data;
using BasicServer.DAL.Models;
using Microsoft.OpenApi.Models;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Item Catalog API", Version = "v1" });
});

// Register ItemService in the DI container
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();

var app = builder.Build();

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

// Use reflection to register methods marked with EndpointAttribute as endpoints
var itemService = app.Services.GetRequiredService();
var methods = itemService.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);

foreach (var method in methods)
{
var attribute = method.GetCustomAttribute();
if (attribute != null)
{
var httpMethod = attribute.HttpMethod.ToUpper();
var route = attribute.Route;

// Use an anonymous function to handle parameters dynamically
app.MapMethods(route, new[] { httpMethod }, async (HttpContext context) =>
{
var parameters = method.GetParameters();
var args = new object[parameters.Length];

for (int i = 0; i < parameters.Length; i++)
{
var parameter = parameters;
if (parameter.ParameterType == typeof(int) && context.Request.RouteValues.TryGetValue(parameter.Name, out var value))
{
args = int.Parse(value.ToString());
}
else if (parameter.ParameterType == typeof(Item) && context.Request.Method == "POST" || context.Request.Method == "PUT")
{
args = await context.Request.ReadFromJsonAsync();
}
else if (parameter.ParameterType == typeof(string) && context.Request.Query.TryGetValue(parameter.Name, out var queryValue))
{
args = queryValue.ToString();
}
else
{
args = null;
}
}

var result = method.Invoke(itemService, args);
if (result is Task task)
{
await task;
if (task.GetType().IsGenericType)
{
var resultValue = task.GetType().GetProperty("Result")?.GetValue(task);
if (resultValue != null)
{
await context.Response.WriteAsJsonAsync(resultValue);
}
else
{
context.Response.StatusCode = StatusCodes.Status204NoContent;
}
}
}
else if (result != null)
{
await context.Response.WriteAsJsonAsync(result);
}
});
}
}

app.Run();

server.csproj:



net8.0
enable
enable













Подробнее здесь: https://stackoverflow.com/questions/790 ... -endpoints
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

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