ASP.NET MVC ModelBinding 继承类

发布于 2024-08-13 07:25:02 字数 730 浏览 10 评论 0 原文

我有一个关于 ASP.NET MVC(我正在使用 MVC 2 预览版 2)中与继承相关的 ModelBinding 的问题。

假设我有以下接口/类:

interface IBase
class Base : IBase
interface IChild
class Child: Base, IChild

我有一个自定义模型绑定器 BaseModelBinder。

以下工作正常:

ModelBinders.Binders[typeof(Child)] = new BaseModelBinder();
ModelBinders.Binders[typeof(IChild)] = new BaseModelBinder();

以下工作不起作用(在绑定 Child 类型的对象时):

ModelBinders.Binders[typeof(Base)] = new BaseModelBinder();
ModelBinders.Binders[typeof(IBase)] = new BaseModelBinder();

是否有任何方法可以为适用于所有继承类的基类提供模型绑定器?我真的不想为每个可能的继承类手动输入一些内容。

另外,如果可能的话,是否有办法重写特定继承类的模型绑定器?假设我已经完成了这个工作,但我需要一个针对 Child2 的特定模型绑定器。

提前致谢。

I've got a question about ModelBinding in ASP.NET MVC (I'm using MVC 2 preview 2) related to inheritance.

Say I have the following interfaces/classes:

interface IBase
class Base : IBase
interface IChild
class Child: Base, IChild

And I have a custom model binder BaseModelBinder.

The following work fine:

ModelBinders.Binders[typeof(Child)] = new BaseModelBinder();
ModelBinders.Binders[typeof(IChild)] = new BaseModelBinder();

The following do not work (on binding a on object of type Child):

ModelBinders.Binders[typeof(Base)] = new BaseModelBinder();
ModelBinders.Binders[typeof(IBase)] = new BaseModelBinder();

Is there any way to have a model binder for a base class that will apply to all inherited classes? I really don't want to have to manually input something for every possible inheriting class.

Also, if it is possible, is there a way to override the modelbinder for a specific inheriting class? Say I got this working but I needed a specific modelbinder for Child2.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

习惯成性 2024-08-20 07:25:02

我采取了一个简单的路线,我只是在启动时使用反射动态注册所有派生类。也许这不是一个干净的解决方案,但它是初始化代码中的几行代码,可以正常工作;-)

但是如果你真的想搞乱模型绑定器(你必须 - 最终 - 但有是消磨时间的更好方式;-) 您可以阅读 这个这个

I took a simple route, I just register all derived classes dynamically at startup using reflection. Maybe it's not a clean solution, but it's couple of lines in the initialization code that just works ;-)

But if you really want to mess with model binders (you'll HAVE to - eventually - but there're better ways to spend your time ;-) you can read this and this.

塔塔猫 2024-08-20 07:25:02

好吧,我想一种方法是对 ModelBindersDictionary 类进行子类化并重写 GetBinders(Type modelType, bool FallbackToDefault) 方法。

public class CustomModelBinderDictionary : ModelBinderDictionary
{
    public override IModelBinder GetBinder(Type modelType, bool fallbackToDefault)
    {
        IModelBinder binder = base.GetBinder(modelType, false);

        if (binder == null)
        {
            Type baseType = modelType.BaseType;
            while (binder == null && baseType != typeof(object))
            {
                binder = base.GetBinder(baseType, false);
                baseType = baseType.BaseType;
            }
        }

        return binder ?? DefaultBinder;
    }
}

基本上遍历类层次结构,直到找到模型绑定器或默认为 DefaultModelBinder

下一步是让框架接受 CustomModelBinderDictionary。据我所知,您需要对以下三个类进行子类化并重写 Binders 属性:DefaultModelBinderControllerActionInvokerController。您可能想要提供自己的静态 CustomModelBinders 类。

免责声明:这只是一个粗略的原型。我不确定它是否真的有效,它可能会产生什么影响,或者它是否是一个合理的方法。您可能需要自己下载该框架的代码并进行实验。

更新

我想另一种解决方案是定义您自己的CustomModelBindingAttribute

public class BindToBase : CustomModelBinderAttribute
{
    public override IModelBinder GetBinder()
    {
        return new BaseModelBinder();
    }
}

public class CustomController
{
   public ActionResult([BindToBase] Child child)
   {
       // Logic.
   }
}

Well, I guess one way of doing it is to sub-class the ModelBindersDictionary class and override the GetBinders(Type modelType, bool fallbackToDefault) method.

public class CustomModelBinderDictionary : ModelBinderDictionary
{
    public override IModelBinder GetBinder(Type modelType, bool fallbackToDefault)
    {
        IModelBinder binder = base.GetBinder(modelType, false);

        if (binder == null)
        {
            Type baseType = modelType.BaseType;
            while (binder == null && baseType != typeof(object))
            {
                binder = base.GetBinder(baseType, false);
                baseType = baseType.BaseType;
            }
        }

        return binder ?? DefaultBinder;
    }
}

Basically walk the class hierarchy until a model binder is found or default to the DefaultModelBinder.

The next step is making the framework accept the CustomModelBinderDictionary. As far as I can tell you need to sub-class the following three classes and override the Binders property: DefaultModelBinder, ControllerActionInvoker and Controller. You might want to provide your own static CustomModelBinders class.

Disclaimer: This is just a rough prototype. I'm not sure if it's actually working, what implications it might have or if it is a sound approach. You might want to download the code for the framework yourself and experiment.

Update:

I guess an alternative solution would be to define your own CustomModelBindingAttribute.

public class BindToBase : CustomModelBinderAttribute
{
    public override IModelBinder GetBinder()
    {
        return new BaseModelBinder();
    }
}

public class CustomController
{
   public ActionResult([BindToBase] Child child)
   {
       // Logic.
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文