Вы можете воспользоваться шаблоном Factory, который будет возвращать теги, которые вы хотите создать, основываясь на входных данных JSON. Создайте фабрику, назовите ее TagsFactory, которая реализует следующий интерфейс:
public interface ITagsFactory
{
string CreateTags(int dataType, string jsonInput);
}
Создайте фабрику тегов, как показано ниже:
public class TagsFactory : ITagsFactory
{
public string CreateTags(int dataType, string jsonInput)
{
switch(dataType)
{
case 1:
var intTagsDto = JsonConvert.DeserializeObject<TagForCreateDto1(jsonInput);
// your logic to create the tags below
...
var tagsModel = GenerateTags();
return the JsonConvert.SerializeObject(tagsModel);
case 5:
var ListTagsDto = JsonConvert.DeserializeObject<TagForCreateDto2>(jsonInput);
// your logic to create the tags below
...
var tagsModel = GenerateTags();
return the JsonConvert.SerializeObject(tagsModel);
}
}
}
Для еще большего разделения интересов вы можете переместить логику GenerateTags с фабрики в ее собственный класс.
После того, как все вышеперечисленное введено в действие, я бы предложил немного изменить дизайн вашего
TagsController
. Добавьте следующие параметры к действию CreateTags
- тип данных или имя тега. Все, что легче обрабатывать и читать, используя
[FromHeader]
- jsonInput и считайте его, используя
[FromBody]
Ваш контроллер будет выглядеть как показано ниже, используя ITagsFactory, введенный через DI
[Route("api")]
public class TagsController : Controller
{
private readonly ITagsFactory _tagsFactory;
public TagsController(ITagsFactory tagsFactory)
{
_tagsFactory= tagsFactory;
}
[HttpPost]
[Route("tags")]
public IActionResult CreateTags([FromHeader(Name = "data-type")] string dataType, [FromBody] string jsonInput)
{
var tags = _tagsFactory.CreateTags(dataType, jsonInput);
return new ObjectResult(tags)
{
StatusCode = 200
};
}
}
Работа почти завершена. Однако, чтобы прочитать необработанные входные данные JSON из тела, вам нужно добавить CustomInputFormatter
и зарегистрировать его при запуске
public class RawRequestBodyInputFormatter : InputFormatter
{
public RawRequestBodyInputFormatter()
{
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json"));
}
public override bool CanRead(InputFormatterContext context)
{
return true;
}
public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
var request = context.HttpContext.Request;
using (var reader = new StreamReader(request.Body))
{
var content = await reader.ReadToEndAsync();
return await InputFormatterResult.SuccessAsync(content);
}
}
}
Зарегистрируйте форматер и TagsFactory
в автозагрузке, как показано ниже:
services.AddSingleton<ITagsFactory, TagsFactory>();
services.AddMvc(options =>
{
options.InputFormatters.Insert(0, new RawRequestBodyInputFormatter());
}
Таким образом, ваша конечная точка останется прежней. Если вам нужно добавить больше TagTypes, вам просто нужно добавить этот случай в TagsFactory
. Вы, вероятно, можете подумать, что это нарушение OCP. Однако Фабрике нужно знать, какой объект ей нужно создать. Если вам нравится больше абстрагироваться, вы можете использовать AbstractFactory, но я думаю, это было бы излишним.