C# MVC脚手架正在复制我的模型字段
我似乎遇到了一个奇怪的问题,在几个小时的挠头之后,我似乎把问题缩小到了和的组合。当我重写位于单独文件中的分部类中的属性时,MVC会复制视图中的字段。我正在使用Visual Studio 2013,可以通过以下步骤复制此问题:C# MVC脚手架正在复制我的模型字段,c#,asp.net-mvc,asp.net-mvc-5,C#,Asp.net Mvc,Asp.net Mvc 5,我似乎遇到了一个奇怪的问题,在几个小时的挠头之后,我似乎把问题缩小到了和的组合。当我重写位于单独文件中的分部类中的属性时,MVC会复制视图中的字段。我正在使用Visual Studio 2013,可以通过以下步骤复制此问题: 打开Visual Studio并创建新项目。在类别下选择Web,然后选择“ASP.NET Web应用程序”。我的目标是.NET4.5 从模板选择中选择“Empty”,然后选中MVC复选框,以便添加核心文件夹和引用 创建项目后,右键单击Models文件夹并创建一个名为MyMo
Models
文件夹并创建一个名为MyModel.cs
的新类李>
将以下行添加到新文件:
public abstract partial class MyOriginalModel
{
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
public partial class MyModel : MyOriginalModel
{
}
Models
文件夹,创建另一个名为MyModelCustom.cs
的新类public partial class MyModel
{
[System.ComponentModel.DisplayName("First Name")]
[System.ComponentModel.DataAnnotations.Required]
public override string FirstName
{
get
{
return base.FirstName;
}
set
{
base.FirstName = value;
}
}
[System.ComponentModel.DisplayName("Last Name")]
[System.ComponentModel.DataAnnotations.Required]
public override string LastName
{
get
{
return base.LastName;
}
set
{
base.LastName = value;
}
}
}
Controllers
文件夹并添加新的控制器。选择“具有读/写操作的MVC5控制器”,并将其命名为NamesController
。右键单击Create方法并转到“添加视图”。在模板下拉列表下,选择创建,并在模型类下拉列表中选择MyModel李>
一旦MVC创建了模板,您将看到它添加了两次名字
和姓氏
。这个问题似乎与部分类有关,因为如果我将MyModelCustom.cs
的内容移动到MyModel.cs
中,一切正常。然而,它不仅仅是部分类。如果我在分部类中创建一个新属性(而不是重载一个),它不会复制该属性。因此,它似乎是部分类和重写虚拟属性的组合
有人能确认这是一个bug还是我做错了什么吗?两者都有一点。无论是否有缺陷,如果MVC的搭建方式不正确,您要么必须不断地与框架抗争,要么改变解决问题的方法 作为一般规则,我发现当你不得不与MVC框架抗争以使其按你想要的方式运行时,那么改变解决问题的方法就容易多了。否则,你最终将反复进行这场战斗,直到你最终服从。从一个以艰苦的方式吸取教训的人身上吸取教训 考虑到更简单的方法,您可以尝试以下几点:
查看用于MVCSCapfolding的CodePlex源代码
//
///在一组代码类型实例中,其中一些可能是同一类的不同部分。
///这个方法过滤掉这样一个集合,这样每个类只能得到一个分部。
///
私有静态列表PickArbitraryRepresentativeOfpPartialClass(IEnumerable代码类型)
{
var代表=新列表();
foreach(代码类型中的var代码类型){
var codeClass2=codeClass2的代码类型;
if(codeClass2!=null){
var matcheseExistingRepresentative=(来自representations.OfType()中的候选者)
让candidatePartials=candidate.partialClass.OfType()
其中candidatePartials.Contains(codeClass2)
选择候选者);
如果(!匹配现有代表)
添加(代码类型);
}否则{
//不能有partials,因为它不是CodeClass2,所以不能与其他类冲突
添加(代码类型);
}
}
返回代表;
}
}
:
:
1)PickArbitraryRepresentativeOfPartialClasses
,该方法使用Linqany()
确认作为CodeClass2的codeType具有成员
是Visual Studio的核心自动化库的部分类类型,该库负责IDE代码生成(设计时反射)
2)如果强制转换为CodeClass2
的类确实有成员,则该类将添加到代表中
3)计算分部类时,将在不同的上下文中访问每个文件(通常会导致合并应重写的元素)
运行时反射和设计时反射之间有趣的区别:
ASP.NET控件有两组不同的功能,用于在运行时在页面内执行或在宿主设计器内在设计时使用。运行时功能根据配置确定控件输出的标记。相反,设计时功能得益于可视化设计器,如Microsoft visual Studio 2005。设计时功能允许页面作者以声明式和所见即所得(WYSIWYG)的方式为运行时配置控件
结论:
MVC脚手架确实使用了反射,但它的可靠性要低得多
设计时反射与运行时反射不同。完全编译的类是继承的最终结果
/// <summary>
/// Out of a set of CodeType instances, some of them may be different partials of the same class.
/// This method filters down such a set so that you get only one partial per class.
/// </summary>
private static List<CodeType> PickArbitraryRepresentativeOfPartialClasses(IEnumerable<CodeType> codeTypes)
{
var representatives = new List<CodeType>();
foreach (var codeType in codeTypes) {
var codeClass2 = codeType as CodeClass2;
if (codeClass2 != null) {
var matchesExistingRepresentative = (from candidate in representatives.OfType<CodeClass2>()
let candidatePartials = candidate.PartialClasses.OfType<CodeClass2>()
where candidatePartials.Contains(codeClass2)
select candidate).Any();
if (!matchesExistingRepresentative)
representatives.Add(codeType);
} else {
// Can't have partials because it's not a CodeClass2, so it can't clash with others
representatives.Add(codeType);
}
}
return representatives;
}
}