C# 自动生成视图模型
我正在用C#将web应用程序从PHP重写为MVC.NET。 通过逆向工程,我生成了EF数据库模型 由于原始应用程序包含许多表(实体),因此我想从数据库(或EF中的实体)中以某种方式使用以下属性预生成MVC ViewModelsC# 自动生成视图模型,c#,asp.net-mvc,code-generation,visual-studio-2013,C#,Asp.net Mvc,Code Generation,Visual Studio 2013,我正在用C#将web应用程序从PHP重写为MVC.NET。 通过逆向工程,我生成了EF数据库模型 由于原始应用程序包含许多表(实体),因此我想从数据库(或EF中的实体)中以某种方式使用以下属性预生成MVC ViewModels [Required] [Display(Name = "columnName")] [StringLength(100)] ... ... 只需通过近似数据库,我就可以编辑一些属性viewmodel,以便在视图中使用 有没有人做过类似的事情,或者知道VS或插件工具的任何
[Required]
[Display(Name = "columnName")]
[StringLength(100)]
...
...
只需通过近似数据库,我就可以编辑一些属性viewmodel,以便在视图中使用
有没有人做过类似的事情,或者知道VS或插件工具的任何扩展
非常感谢实现这一点的“工具”是所谓的t4模板,这是一个可以在visual studio中使用的功能,您可以在其中生成所需的任何内容
尽管调试这些模板并不是那么容易,但要小心;)
:编辑:如果您不想自己投入太多精力,您可以使用第三方工具,围绕t4构建框架,这是一个很棒的工具,可以从EF或NHibernate模型生成控制器+视图。或者至少您可以查看内置模板并对其进行编辑…我创建了一个visual studio t4模板来实现这一点。它将抓取如下文件:
using MicroMvvm;
namespace MyApplication
{
[Bindable]
public partial class MyApplication
{
[Bindable]
private string _ipAdress;
[Bindable]
private MyChild _child;
public MyApplication()
{
IpAdress = "ip adress test";
Child = new MyChild(this, "");
}
[Bindable]
void AddDot()
{
IpAdress += ".";
}
[Can]
bool CanChangeChild()
{
return IpAdress.Trim().Length != 0;
}
[Bindable]
void ChangeChild()
{
Child = new MyChild2(this);
}
}
}
并生成此文件:
using System;
using System.ComponentModel;
using System.Windows.Input;
using MicroMvvm;
namespace MyApplication
{
public partial class MyApplication : INotifyPropertyChanged
{
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(String propertyName)
{
var handler = PropertyChanged;
if (handler == null) return;
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
public String IpAdress
{
get { return _ipAdress; }
set
{
_ipAdress = value;
RaisePropertyChanged("IpAdress");
}
}
public MyChild Child
{
get { return _child; }
set
{
_child = value;
RaisePropertyChanged("Child");
}
}
public ICommand AddDotCommand { get { return new RelayCommand(AddDot, null); } }
public ICommand ChangeChildCommand { get { return new RelayCommand(ChangeChild, CanChangeChild); } }
}
}
这是模板,您需要将“MyApplication”更改为包含要变形为viewmodels的对象的项目名称
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ assembly name="$(SolutionDir)MicroMvvm\bin\Debug\MicroMvvm.dll" #>
<#@ assembly name="$(SolutionDir)MyApplication\bin\Debug\MyApplication.dll" #>
<#@ import namespace="MyApplication" #>
using System;
using System.ComponentModel;
using System.Windows.Input;
using MicroMvvm;
namespace MyApplication
{
<#
var assembly = typeof(MyApplication).Assembly;
var types = new HashSet<Type>(assembly.GetTypes().Where(type => Attribute.GetCustomAttribute(type, typeof(MicroMvvm.Bindable)) != null));
var skip = new HashSet<Type>(types.Where(type => types.Contains(type.BaseType)));
foreach (Type type in types)
{
if (Attribute.GetCustomAttribute(type, typeof(MicroMvvm.Bindable)) == null)
continue;
#>
public partial class <#=type.Name#> <#=skip.Contains(type) ? "" : ": INotifyPropertyChanged"#>
{
<#
if (!skip.Contains(type))
{
#>
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(String propertyName)
{
var handler = PropertyChanged;
if (handler == null) return;
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
<#
}
foreach(FieldInfo fieldInfo in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance)) {
if (!Attribute.IsDefined(fieldInfo, typeof(MicroMvvm.Bindable)))
continue;
if (!fieldInfo.Name.StartsWith("_"))
continue;
string fieldName = fieldInfo.Name.Substring(1);
fieldName = char.ToUpper(fieldName[0]) + fieldName.Substring(1);
#> public <#=fieldInfo.FieldType.Name#> <#=fieldName#>
{
get { return <#=fieldInfo.Name#>; }
set
{
<#=fieldInfo.Name#> = value;
RaisePropertyChanged("<#=fieldName#>");
}
}
<#
}
foreach(MethodInfo method in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance)) {
if (!Attribute.IsDefined(method, typeof(MicroMvvm.Bindable)))
continue;
MethodInfo canMethod = null;
foreach(MethodInfo searchMethod in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance)) {
if (Attribute.IsDefined(searchMethod, typeof(MicroMvvm.Can)) && ("Can" + method.Name).Equals(searchMethod.Name))
canMethod = searchMethod;
}
#> public ICommand <#=method.Name#>Command { get { return new RelayCommand(<#=method.Name#>, <#= canMethod == null ? "null" : canMethod.Name #>); } }
<#
}
#>
}
<#
}
#>
}
使用制度;
使用系统组件模型;
使用System.Windows.Input;
使用微型vvm;
命名空间MyApplication
{
GetCustomAttribute(type,typeof(MicroMvvm.Bindable))!=null);
var skip=newhashset(types.Where(type=>types.Contains(type.BaseType));
foreach(类型中的类型)
{
if(Attribute.GetCustomAttribute(type,typeof(MicroMvvm.Bindable))==null)
继续;
#>
公共部分类
{
[字段:非序列化]
公共事件属性更改事件处理程序属性更改;
私有void RaisePropertyChanged(字符串propertyName)
{
var handler=PropertyChanged;
if(handler==null)返回;
var e=新的PropertyChangedEventArgs(propertyName);
处理者(本,e);
}
公开的
{
获取{return;}
设置
{
=价值;
RaisePropertyChanged(“”);
}
}
公共ICommand命令{get{returnnewrelaycommand(,);}
}
}
它还需要MicroMvvm框架和两个系统。属性是可绑定的,并且可以。它显著减少了您需要编写的锅炉板代码。但是边缘有点粗糙。我不确定您想要的是什么。如果您真的在生成
视图模型
,我会提醒您,这是一个非常松散的关系在数据库表和视图模型之间传送。通常,视图
需要合并来自多个表、cookie和用户输入的数据。这不是通常可以预测的,因此是预先生成的。entitydeveloper可以生成ViewModel dy dataAnotations?您好,这很好,但是pr的映射迭代EF对象期间的属性并不总是有效