问题
I'm trying to implement this kind of mechanizm:
Model has bit field: is_active
, so I'm using it to toggle visibility on the main form. The action in controler is like:
public ActionResult Toggle(int id)
{
Country country = _db.Countries.Find(id);
country.is_active = country.is_active == null ? true : !country.is_active;
_db.SaveChanges();
return RedirectToAction("Index");
}
I want my admin lookup controllers to derive from that generic class and use the implementation from it for common actions like toggle.
I've already created ITogglable interface that has ActionResult Toggle(int id)
so I'm implementing it inside particular controler (CountryController : Controller, ITogglable
), but I have to implement it every time. Instead I would more like my CountryController, RegionController, etc derive from a generic class (i.e. Togglable
) that has these kind of methods already implemented like:
public virtual ActionResult Toggle(int id)
{
CurrentModelTypeUsedInController lookup = _db.CurrentModelTypeUsedInController.Find(id);
lookup .is_active = lookup .is_active == null ? true : !lookup.is_active;
_db.SaveChanges();
return RedirectToAction("Index");
}
Is this even possible? I have no idea how to make it lookup-independant so I do not have to provide type of CurrentModelTypeUsedInController
each time.
回答1:
You need a couple of abstractions to achieve this.
Firstly you will need an abstraction that defines is_active
, such as
public interface IActive
{
bool is_active { get; set; }
}
And all of the types such as Country
and CurrentModelTypeUsedInController
will need to implement this abstraction
public class Country : IActive
{
public bool is_active { get; set; }
}
And with this in place we define the generic controller. The key point here is the generic constraint (IActive
) that is placed on generic type (TModelType
). By defining that all types of TModelType
must implement IActive
the code knows that the type is guaranteed to expose a property named is_active
public class AbstractController<TModelType> : Controller
where TModelType : class, IActive
{
private readonly DbContext _db;
public AbstractController()
{
_db = new DbContext("connection");
}
public ActionResult Toggle(int id)
{
TModelType instance = _db.Set<TModelType>().Find(id);
instance.is_active = instance.is_active == null ? true : !instance.is_active;
_db.SaveChanges();
return RedirectToAction("Index");
}
}
And each controller can derive from AbstractController<>
public sealed class CountryController : AbstractController<Country>
{
}
来源:https://stackoverflow.com/questions/24755523/asp-net-mvc-entity-framework-generic-model-independent-controller-class-implem