简体   繁体   English

解决通用接口中的 static 方法

[英]workaround a static method in a generic interface

I have a business model TodoItem .我有一个业务 model TodoItem I have an API that gives me todoitems .我有一个 API 给我todoitems So, I have a corresponding TodoItemModel for each controller (let's name it TodoItemDTO ).所以,我对每个 controller 都有一个对应的 TodoItemModel (我们将其命名为TodoItemDTO )。

The TodoItemDTO class should be able to load itself from a TodoItem business class. TodoItemDTO class 应该能够从TodoItem业务 class 加载自身。 So, usually, we would write a static method on the TodoItemDTO class TodoItemDTO FromTodoItem(TodoItem todoItem) .因此,通常,我们会在TodoItemDTO class TodoItemDTO FromTodoItem(TodoItem todoItem)上编写 static 方法。

I would like to define an interface for such classes.我想为这些类定义一个接口。 But unfortunately I can't define a static method in an interface... ( note : I use the latest C# version, so, finally, I do, but I should define it... however each class should define its static method) But unfortunately I can't define a static method in an interface... ( note : I use the latest C# version, so, finally, I do, but I should define it... however each class should define its static method)

Here is what I tried:这是我尝试过的:

public interface IDtoModel<TBussinesModel, TDtoModel>
{
    TDtoModel FromBusinessModel(TBussinesModel businessObject);
}


public class ToDoItemDTO : IDtoModel<ToDoItem, ToDoItemDTO>
{
    public int Id { get; set; }
    [Required]
    public string Title { get; set; }
    public string Description { get; set; }
    public bool IsDone { get; private set; }

    public ToDoItemDTO FromBusinessModel(ToDoItem businessObject)
    {
        return new ToDoItemDTO()
        {
            Id = businessObject.Id,
            Title = businessObject.Title,
            Description = businessObject.Description,
            IsDone = businessObject.IsDone
        };
    }
}

The only 'problem' here is I have a class method that should be, normally, a static method.这里唯一的“问题”是我有一个class方法,通常应该是一个static方法。

So, by eg, when I define a generic controller, I need to create new objects without any need:因此,例如,当我定义一个通用 controller 时,我需要创建新对象而不需要:

[Route("api/[controller]")]
[ApiController]
public abstract class BaseApiController<TBussinesModel, TDtoModel> : Controller
    where TBussinesModel : BaseEntity
    where TDtoModel : IDtoModel<TBussinesModel, TDtoModel>, new()        
{
    protected readonly IRepository _repository;
    public BaseApiController(IRepository repository) { _repository = repository; }

    [HttpGet("{id:int}")]
    public async Task<IActionResult> GetById(int id)
    {
        var businessObject = await _repository.GetByIdAsync<TBussinesModel>(id);
        // 
        // here bellow, I need to create a new object
        // 
        var dtoObject = (new TDtoModel()).FromBusinessModel(businessObject);
        return Ok(dtoObject);
    }

    [HttpPost]
    public abstract Task<IActionResult> Post([FromBody] TDtoModel item);
}

There are lots of options, none of them perfect.有很多选择,没有一个是完美的。

Personally, I would start by turning your factory method into a constructor of the DTO;就个人而言,我首先将您的工厂方法转换为 DTO 的构造函数;

    public ToDoItemDTO(ToDoItem businessObject)
    {
        Id = businessObject.Id;
        Title = businessObject.Title;
        Description = businessObject.Description;
        IsDone = businessObject.IsDone;
    }

You could define a factory class for each DTO.您可以为每个 DTO 定义一个工厂 class。 You could use Activator.CreateInstance to dynamically call the constructor at runtime.您可以使用Activator.CreateInstance在运行时动态调用构造函数。

Or you can locate the constructor with reflection, build an Expression tree and compile it.或者您可以使用反射定位构造函数,构建表达式树并编译它。

    static Func<TBussinesModel, TDtoModel> GetFactory<TBussinesModel, TDtoModel>()
    {
        var p = Expression.Parameter(typeof(TBussinesModel), "p");
        return Expression.Lambda<Func<TBussinesModel, TDtoModel>>(
            Expression.New(
                typeof(TDtoModel).GetConstructor(new Type[] { typeof(TBussinesModel) }),
                p
            ),
            p)
            .Compile();
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM