.Net MVC在运行时将动态类型绑定到模型

时间:2013-05-11 12:20:46

标签: c# asp.net-mvc-4

我有一个稍长的概念性问题,我想知道是否有人可以帮助我。

在MVC中,我建立了一个使用kendoui's framework构建网格的网站。

我网站上的所有网格构建完全相同,除了他们使用的模型和需要为每个模型实现的CRUD方法。我设置了每个Model为下面的CRUD方法实现接口的地方,以便在一个地方获得逻辑。

//Actual interface has variables getting passed
public interface IKendoModelInterface 
{
    void Save();
    void Read();
    void Delete();
}

public class Model1: IKendoModelInterface 
{

    [Key]
    public int IdProperty1 { get; set; }

    public int SomeProperty2 { get; set; }

    public string SomeProperty3 { get; set; }

    public void Save(){
        //Implement Save
    }

    public void Read(){
        //Implement Read
    }

    public void Delete(){
        //Implement Delete
    }
}

然后为了加快编写使网格工作所需的所有脚手架Action方法,我创建了一个抽象的Controller,它可以调用传递给它的Model的接口方法。

    //Implement the AJAX methods called by the grid
    public abstract class KendoGridImplController<T> : Controller where T : class, IKendoModelInterface
{
    // Method called from kendo grid
    public virtual ActionResult Create([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<T> createdRecords) 
    {
        //Invoke Create Method for Model and return results
    }

     public virtual ActionResult Read([DataSourceRequest]DataSourceRequest request, int Id)
    {
      //Invoke read method for model and return results
    }
    //Update and Delete also implemented..

 }

然后我只需要一个每个模型的Controller,它实现上面抽象控制器传递所使用的Model类型。

     public class ResponsibilityMatrixController :  KendoGridImplController<Model1>
{
   //Set up the page the grid will be on 
    public ActionResult Index(int id)
    {

        return View("SharedGridView", id);
    }
    //Can override abstract methods if needed but usually won't need to
}

我想知道我是否可以更进一步,或者我是否已经走到了尽头。对我而言,如果我必须为每个模型创建一个除了将类型传递给抽象控制器并调用相同视图的模型之外,它似乎就是更多重复的代码。

昨天我试图弄清楚是否可以动态地将类型分配给抽象控制器。我设置了一些我通过字符串发回模型类型的东西,我仍然可以调用所需的方法。失败的地方是,默认情况下无法在任何控制器操作上完成映射,因为在编译时不知道该类型。例如

public virtual ActionResult Create([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<T> createdRecords) 
如果传入的T是一个接口而不是模型本身,那么

createdRecords就不能像这样绑定了。我发现没有真正的方法将表单数据映射到一个在编译时不知道的类型的实例时间。

我想知道是否有一种简单的方法可以在传递的对象类型的实例之间执行此映射,我可以在运行时找出,如果有其他方法设置它我忽略或如果这两件事都要做太多工作而且我不应该尝试这样的事情并按照我现在的方式为每个模型构建一个控制器?

1 个答案:

答案 0 :(得分:0)

如果其他人在将来发现这一点,我到目前为止所做的就是解决我的问题。首先,我下载了impromptu-interface代码库,这在处理动态类型时非常有用。

然后对于抽象控制器的保存方法,重要的是我可以绑定回原始对象类型,我这样做了。

// Method called from kendo grid
public virtual ActionResult Create([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<ExpandoObject> createdRecords) 
{
    Type originalGridType = GetTypeOfModelUsingCustomCodeIDevelopedEarlier();
    foreach (ExpandoObject record in createdRecords)
    {
        var convertedType = Impromptu.InvokeConvert(record, originalGridType);
        T objectInstance = Impromptu.ActLike(convertedType);
        objectInstance.Save();
    }

}

然后我只需要在我的模型中添加一个可以从ExpandoObject转换为我的模型的模型。我仍然希望有一个额外的方法不必存在,但是我写了一些辅助方法,并没有更多的代码可以实现。

    public static implicit operator Model1(ExpandoObject expando)
    {
        Model1 model = new Model1();
        //Set fields of model...
        //....
        return model;
    }

从这里开始,一切都在前后工作。也许有更好的方法,但这是迄今为止我能想到的最好方法。