抽象类可以作为控制器动作的参数吗?

我在Controller中有一个Action函数,它是用AJAX调用的。 该行动涉及1个参数。 客户端,我构造了一个JSON对象,应该序列化为该1参数。 我遇到的问题是参数类被声明为abstract。 因此,它无法实例化。

当AJAX点击该Action时,我得到以下内容:

无法创建抽象类。

堆栈跟踪:

[MissingMethodException:无法创建抽象类。]
System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,Boolean publicOnly,Boolean noCheck,Boolean&canBeCached,RuntimeMethodHandleInternal&ctor,Boolean&bNeedSecurityCheck)+0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly,Boolean skipCheckThis,Boolean fillCache)+98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly,Boolean skipVisibilityChecks,Boolean skipCheckThis,Boolean fillCache)+241 System.Activator.CreateInstance(Type type,Boolean nonPublic)+69 ……………

有没有办法在不创建不同参数对象的情况下实现这样的场景,“取消声明”参数对象为抽象,或者深入研究MVC的机制?

更新

我目前正在与后端开发人员一起调整他们的对象。 无论哪种方式,我认为这将是最终的解决方案。 谢谢大家的答案。

更新:示例现在使用AJAX JSON POST

如果必须使用抽象类型,则可以提供自定义模型绑定器来创建具体实例。 一个例子如下所示:

型号/型号粘合剂

public abstract class Student { public abstract int Age { get; set; } public abstract string Name { get; set; } } public class GoodStudent : Student { public override int Age { get; set; } public override string Name { get; set; } } public class BadStudent : Student { public override int Age { get; set; } public override string Name { get; set; } } public class StudentBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var values = (ValueProviderCollection) bindingContext.ValueProvider; var age = (int) values.GetValue("Age").ConvertTo(typeof (int)); var name = (string) values.GetValue("Name").ConvertTo(typeof(string)); return age > 10 ? (Student) new GoodStudent { Age = age, Name = name } : new BadStudent { Age = age, Name = name }; } } 

控制器动作

 public ActionResult Index() { return View(new GoodStudent { Age = 13, Name = "John Smith" }); } [HttpPost] public ActionResult Index(Student student) { return View(student); } 

视图

 @model AbstractTest.Models.Student @using (Html.BeginForm()) { 

Age @Html.TextBoxFor(m => m.Age)

Name @Html.TextBoxFor(m => m.Name)

}

添加到Global.asax.cs

 protected void Application_Start() { ... ModelBinders.Binders.Add(new KeyValuePair(typeof(Student), new StudentBinder())); } 

框架无法知道您想要的具体实现,也不会承担此类决策的责任。 所以你有两种可能性:

  1. 使用具体类型作为操作参数
  2. 为这个抽象类编写一个自定义模型绑定器,它基于一些请求参数将返回一个特定的实例。

您将不得不创建抽象类的子类并将其传递给它。 从根本上说,抽象类不允许自己实例化。 但是,如果你有一个C#方法,如:

 protected void Foo(MyAbstractClass param1) 

…然后你仍然可以传递Foo一个派生自MyAbstractClass的类型的实例。 因此,您可以创建一个具体的子类MyChildClass : MyAbstractClass并将其传递给您的方法,它应该仍然有效。 您不必更改Foo方法,但您需要访问C#代码,以便创建MyChildClass

如果您正在使用generics – 例如,如果您的方法签名是:

 protected void Foo(IEnumerable param1) 

…然后它变得更加复杂,你会想要研究C#generics中的协方差和逆变 。

如果您有权访问控制器,您可以添加另一个inheritance抽象类的类而不指定任何成员,并使用它来序列化反序列化,然后将其基础返回到另一个层吗?

我知道这不是一个好习惯,但有些黑客但我不知道抽象类是否可以某种方式序列化。

不 – 试图将JSON反序列化为抽象类的对象是没有意义的。 你能不能成为一个合适的class级?