在接口中使用泛型和实现可选字段,或可选地实现接口
本文关键字:实现 接口 字段 泛型 | 更新日期: 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
模型字段。
然而,只有我的一些模型具有DateCreated
和CreatedBy
属性,我想在我的通用控制器的Edit
方法中更新这些属性。
像这样的
model.DateCreated = DateTime.Now;
model.CreatedBy = _myService.Username;
然而,为了做到这一点,我必须将这两个属性添加到IEntity
接口,但这些属性只属于某些模型,例如Lookup2
没有这两个属性。
我能想到的唯一解决方案是将nullable
DateCreated
和CreatedBy
属性添加到我的所有模型类中,这样我就可以将这些属性添加到IEntity
接口并更新我的通用控制器中的这些字段。然而,我不认为这是理想的,因为我没有兴趣为Lookup2
设置这些属性
我的问题:
是否可以在接口中具有条件属性或可选地继承单独的条件接口?
或另一个更整洁的解决方案来解决我的问题?
使用其他接口:
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);