Можно ли изменить этот метод расширения, чтобы он имел более чистый синтаксис? - PullRequest
1 голос
/ 06 марта 2020

Классы модели моего домена наследуются от:

BaseModel<T>

, например:

public partial class WarehouseType : BaseModel<WarehouseType>
{}

Я пытаюсь добавить метод расширения к базовой модели как:

public static class BaseModelExtensionMethods
{
    public static TDto ToDto<TDto, TModel>(this Model.SharedKernel.BaseModel<TModel> model)
    {
        return Globals.mapper.Map<TDto>(model);
    }
}

И вот как я это использую:

Model.Inventory.WarehouseType warehouseType = new Model.Inventory.WarehouseType();

warehouseType.ToDto<V1.Messages.WarehouseTypeDto, Model.Inventory.WarehouseType>();

Как показано в приведенном выше коде, мне нужно передать два типа (TDto, TModel) в ToDto<> метод расширения.

Я хочу знать, возможно ли изменить синтаксис ToDto <> таким образом, чтобы мне не нужно было передавать TModel в ToDto<> и получать тип TModel внутри метода например, в соответствии с типом объекта, который вызывает метод расширения? Есть ли обходной путь или волхвы c, чтобы сделать такую ​​вещь? Мне это нужно, чтобы код стал более понятным и простым в использовании.

Идеальный искомый синтаксис выглядит следующим образом:

warehouseType.ToDto<V1.Messages.WarehouseTypeDto>();

Ответы [ 2 ]

3 голосов
/ 07 марта 2020

Вы можете попробовать это

public class BaseModel { }
public class BaseModel<T> : BaseModel { }

Затем создайте метод расширения для BaseModel

public static class BaseModelExtensionMethods
{
public static TDto ToDto<TDto>(this Model.SharedKernel.BaseModel model)
{
    return Globals.mapper.Map<TDto>(model);
}
}
1 голос
/ 07 марта 2020

C# не допускает частичной оценки (или вывода) параметров типа для обобщенных c типов или методов (вы можете переключиться на F #, что делает). Таким образом, у вас есть несколько вариантов - вы можете выбрать обобщение по шагам, если вы хотите создать промежуточный класс для запоминания предполагаемого типа, или создать специализации, или вы не можете сделать вывод о типах.

Чтобы сделать это в шаги, вы должны разбить метод ToDto на две части и использовать промежуточный класс для переноса выведенного типа. Вызовите этот класс Toer (см. Также этот ответ ):

public class Toer<TModel> {
    Model.SharedKernel.BaseModel<TModel> model;

    public Toer(Model.SharedKernel.BaseModel<TModel> model) => this.model = model;
    public TDto Dto<TDto>() => Globals.mapper.Map<TDto>(model);
}

Теперь вы создаете метод расширения, который возвращает объект Toer:

public static Toer<TModel> To<TModel>(this Model.SharedKernel.BaseModel<TModel> model) => new Toer<TModel>(model);

Теперь вы можете заменить свой старый код:

var wtDto = warehouseType.ToDto<WarehouseTypeDto, Model.Inventory.WarehouseType>();

На новый код:

var wtDto = warehouseType.To().Dto<WarehouseTypeDto>();

Кроме того, вы можете создать специализации для каждого возможного TModel:

public static TDto ToDto<TDto>(this Model.SharedKernel.BaseModel<Model.Inventory.WarehouseType> model) => Globals.mapper.Map<TDto>(model);

, который вы можете использовать по своему усмотрению.

Наконец, вы можете специализации, которые предварительно кодируют отображение в соответствующий тип DTO, и использовать их:

public static WarehouseTypeDto ToDto(this Model.SharedKernel.BaseModel<Model.Inventory.WarehouseType> model) => Globals.mapper.Map<WarehouseTypeDto>(model);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...