我认为,我在我构建的管理应用程序中所做的事情与您所说的类似。基本上,关键是使用泛型。换句话说,您创建一个控制器,如下所示:
public abstract class AdminController<TEntity> : Controller
where TEntity : IEntity, class, new()
{
protected readonly ApplicationDbContext context;
public virtual ActionResult Index()
{
var entities = context.Set<TEntity>()
return View(entities);
}
public virtual ActionResult Create()
{
var entity = new TEntity();
return View(entity);
}
[HttpPost]
public virtual ActionResult Create(TEntity entity)
{
if (ModelState.IsValid)
{
context.Set<TEntity>().Add(entity);
context.SaveChanges();
return RedirectToAction("Index");
}
return View(entity);
}
...
}
换句话说,您只需构建一个完整的可重用控制器结构,关键部分是您使用的是通用的TEntity 而不是具体的类。请注意,TEntity 定义为 IEntity, class, new()。这做了几件事。首先,class 允许您将其视为具体类型,new() 表示该类型将是可以实例化的东西,而不是抽象类之类的东西。 IEntity 只是您在应用程序中可能使用的任何内容的占位符,以确保所有类型都有一些共同点。至少对于 CRUD 样式的应用程序,您需要它来访问 Id 或类似的属性,例如您的编辑和删除操作。说TEntity 实现IEntity 可以让您利用IEntity 上的任何属性。如果您在此处使用具体类型而不是接口,则可以省略 class 部分,例如where TEntity : Entity, new().
然后,为了使用它,您只需定义一个继承自 AdminController<> 的新控制器并指定您正在使用的类型:
public class WidgetController : AdminController<Widget>
{
public WidgetController(ApplicationDbContext context)
{
this.context = context;
}
}
这可能是您个人控制器所需的全部内容。此外,值得注意的是,我已将其设置为对您的上下文使用依赖注入。您可以随时将构造函数更改为:
public WidgetController()
{
this.context = new ApplicationDbContext();
}
但是,我建议您通常考虑使用依赖注入。另外,为了便于解释,我在这里直接使用上下文,但通常你会在这里使用服务、存储库等。
最后,如果您发现需要自定义 CRUD 操作的某些部分,但不一定是全部,您可以随时添加方法作为扩展点。例如,假设您需要为一个特定实体填充选择列表,您可能会执行以下操作:
public abstract class AdminController<TEntity> : Controller
where TEntity : IEntity, class, new()
{
...
public virtual ActionResult Create()
{
var entity = new TEntity();
BeforeReturnView();
return View(entity);
}
...
protected virtual void BeforeReturnView()
{
}
...
然后:
public class WidgetController : AdminController<Widget>
{
...
protected override void BeforeReturnView()
{
ViewBag.MySelectList = new List<SelectListItem>
{
...
};
}
}
换句话说,您的基本操作方法中有一个钩子,您可以重写它来更改特定的功能,而不必重写整个操作本身。
您还可以进一步包括视图模型之类的内容,您可以在其中将泛型类定义扩展为:
public abstract class AdminController<TEntity, TEntityViewModel, TEntityCreateViewModel, TEntityUpdateViewModel>
where TEntity : IEntity, class, new()
where TEntityViewModel : class, new()
...
然后:
public class WidgetController : AdminController<Widget, WidgetViewModel, WidgetCreateViewModel, WidgetUpdateViewModel>
{
...
}
这完全取决于您的应用程序需要什么。