在接口中使用泛型和实现可选字段,或可选地实现接口

本文关键字:实现 接口 字段 泛型 | 更新日期: 2023-09-27 18:05:47

我使用C# 6.NET 4.6.2

我使用通用存储库和通用ASP.NET MVC Controller,因为我有许多查找表,不想为每个

创建单独的控制器和存储库

下面是我的简化代码:

模型:

public interface IEntity
{
    int Id { get; set; }
}
public class Lookup1:IEntity
{
    public int Id { get; set; }
    public string Lookup1Name { get; set; }
    public string CreatedBy { get; set; }
    public DateTime CreatedDate { get; set; }
}
public class Lookup2:IEntity
{
    public int Id { get; set; }
    public string Lookup2Name { get; set; }
}

存储库:

public interface IGenericRepository<TEntity> where TEntity : class, IEntity
{
    void Update(TEntity obj);
}

public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class, IEntity
{
    public void  Update(TEntity obj)
    {
        table.Attach(obj);
        _db.Entry(obj).State = EntityState.Modified;
    }
}

通用控制器:

 public abstract class GenericController<TModel> : Controller
    where TModel : class,IEntity
{
    private IGenericRepository<TModel> _repository;
    [HttpPost]
    public async Task<IActionResult> Edit(TModel model)
    {
        try
        {
            if (ModelState.IsValid) { 
                _repository.Update(model);
                await _repository.Save();
            }
        }
        catch (Exception)
        {
            ModelState.AddModelError(string.Empty, "Unable to save changes.");
        }
        return View(model);
    }

控制器:

public class Lookup1Controller : GenericController<Lookup1>
{
    private IGenericRepository<Lookup1> _repository;
    public Lookup1Controller (IGenericRepository<Lookup1> repository) : base(repository)
    {
        _repository = repository;
    }
}
public class Lookup2Controller : GenericController<Lookup2>
{
    private IGenericRepository<Lookup2> _repository;
    public Lookup2Controller (IGenericRepository<Lookup2> repository) : base(repository)
    {
        _repository = repository;
    }
}

以上工作并更新从我的MVC视图.cshtml文件传递的所有Lookup1, Lookup2模型字段。

然而,只有我的一些模型具有DateCreatedCreatedBy属性,我想在我的通用控制器的Edit方法中更新这些属性。

像这样的

 model.DateCreated = DateTime.Now;
 model.CreatedBy = _myService.Username;

然而,为了做到这一点,我必须将这两个属性添加到IEntity接口,但这些属性只属于某些模型,例如Lookup2没有这两个属性。

我能想到的唯一解决方案是将nullable DateCreatedCreatedBy属性添加到我的所有模型类中,这样我就可以将这些属性添加到IEntity接口并更新我的通用控制器中的这些字段。然而,我不认为这是理想的,因为我没有兴趣为Lookup2设置这些属性

我的问题:

  1. 是否可以在接口中具有条件属性或可选地继承单独的条件接口?

  2. 或另一个更整洁的解决方案来解决我的问题?

在接口中使用泛型和实现可选字段,或可选地实现接口

使用其他接口:

public interface ITraceableEntity : IEntity
{
     string CreatedBy { get; set; }
     DateTime CreatedDate { get; set; }
}

然后在你想要的具体类上实现它:

public class Lookup1 : ITraceableEntity
{
     public int Id { get; set; }
     public string Lookup1Name { get; set; }
     public string CreatedBy { get; set; }
     public DateTime CreatedDate { get; set; }
}

在通用控制器上,你可以检查实例是否实现了这个接口,然后强制转换它:

try
{
    if (ModelState.IsValid) { 
        if (model is ITraceableEntity)
        {
           ((ITraceableEntity)model).CreatedBy = _myService.Username;  // <---
           ((ITraceableEntity)model).CreatedDate = DateTime.Now;       // <---
        }
        _repository.Update(model);
        await _repository.Save();
    }
}
catch (Exception)
{
    ModelState.AddModelError(string.Empty, "Unable to save changes.");
}
return View(model);