C# 自动生成视图模型

C# 自动生成视图模型,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或插件工具的任何

我正在用C#将web应用程序从PHP重写为MVC.NET。 通过逆向工程,我生成了EF数据库模型

由于原始应用程序包含许多表(实体),因此我想从数据库(或EF中的实体)中以某种方式使用以下属性预生成MVC ViewModels

[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对象期间的属性并不总是有效