我在C#中将Web应用程序从PHP重写为MVC.NET。 通过逆向工程,我生成了EF数据库模型。
由于原始应用程序包含许多表(实体),我想以某种方式从数据库(或来自EF的实体)预生成MVC ViewModel,其属性如
[Required]
[Display(Name = "columnName")]
[StringLength(100)]
...
...
只需通过近似数据库,我就可以编辑一些属性viewmodel,以便在视图中使用。
有没有人做过类似的事情,或者知道VS或插件的任何扩展,工具?
非常感谢
答案 0 :(得分:1)
执行此操作的“工具”是所谓的t4模板,这是您可以在visual studio中使用的功能,您可以在其中基本生成所需的任何内容。
虽然调试这些模板并不容易,但要小心;)
:编辑:如果您不想自己付出太多精力,可以使用第三方工具构建围绕t4的框架,如http://www.devart.com/entitydeveloper/这是一个很棒的工具,可以生成控制器+视图您的EF或NHibernate模型。或者至少你可以看看模板中的构建并编辑它们......
答案 1 :(得分:0)
我创建了一个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”更改为包含要转换为视图模型的对象的项目名称。
<#@ 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 #>); } }
<#
}
#>
}
<#
}
#>
}
它还需要MicroMvvm框架,以及两个System.Attribute的Bindable和Can。它显着减少了您需要编写的锅炉铭牌代码。但它的边缘有点粗糙。