我正在使用 ASP.NET MVC3,我想知道默认的模型绑定器绑定到公共属性而不是公共字段。
通常我只是用属性定义模型类,但有时我使用一些包含一些字段的预定义类。每次我必须调试并记住模型绑定器只是不喜欢字段。
问题:背后的原因是什么?
我正在使用 ASP.NET MVC3,我想知道默认的模型绑定器绑定到公共属性而不是公共字段。
通常我只是用属性定义模型类,但有时我使用一些包含一些字段的预定义类。每次我必须调试并记住模型绑定器只是不喜欢字段。
问题:背后的原因是什么?
但有时我使用一些包含一些字段的预定义类
虽然我无法回答您关于默认模型绑定器仅适用于属性的确切原因的问题(我的猜测是它以这种方式尊重更好的封装并避免修改字段表示的对象的内部状态)我可以说你调用预定义类通常应该是视图模型。您应该始终使用视图模型进出您的控制器操作。这些视图模型是专门为满足给定视图的要求而定义的类。
所以回到要点:字段应该只在给定的类中修改。不应直接从外部访问它们。它们代表并持有类的内部状态。另一方面,属性是应该暴露给外界的。想象一下,在属性 getter/setter 中有一些自定义逻辑。通过直接修改字段,此自定义逻辑将被破坏,并可能使对象进入不一致状态。
也许忽略字段的原因是为了提高活页夹的性能。而不是搜索所有字段和属性。模型绑定器仅搜索属性。
虽然我认为模型绑定器使用缓存来提高性能。
DefaultModelBinder 公开了一个公共方法: DefaultModelBinder.BindModel,以及许多可用于覆盖的受保护方法。所有这些都列在这里。
除了模型之外,这些方法仅引用属性,而不是字段,例如
whereXYZ
代表一个Model,
或Property/ies,
两个,等等。
正如你所看到的,没有Fields
提到这些名字。正如Darin解释的那样,Binder 不会容忍对模型状态的直接更改。因此Field
在其方法中没有。
此外,您不妨看看另一个重要的类:ModelBindingContext。此类的一个实例被传递给BindModel,
并随后传递给BindSimpleModel,
并BindComplexModel,
取决于模型类型(string, int,
... 被认为是简单的,其他一切都是复杂的)。
因此,此上下文具有以下属性:
换句话说,您无法引用 ViewModel 中的字段,除非您不覆盖这些类并采取特殊操作来这样做。
但是,再次提防与框架对抗,它总是更容易遵循它。
编辑:ModelMetadata类包含绑定模型所需的所有数据。然而,它的代码没有显示字段、字段名称等的迹象。只有属性被引用和访问。因此,即使您尝试继承和覆盖DefaultModelBinder和ModelBinderContext,您仍然无法访问字段,更不用说它们的访问修饰符是什么:public、private 等。
希望这能解释大部分。