1

您能否为模型创建自定义数据注释,以便在 T4 模板中读取类似属性的 View。Scaffold 已读取?我想添加数据注释参数,如 Scaffold,我将在此基础上构建视图。

谢谢

4

3 回答 3

5

我写了一篇关于我为 MVC5 提出的解决方案的博客文章。我在这里为任何出现的人发布它: https ://johniekarr.wordpress.com/2015/05/16/mvc-5-t4-templates-and-view-model-property-attributes/

编辑:在您的实体中,使用自定义属性装饰属性

namespace CustomViewTemplate.Models
{     
     [Table("Person")]
     public class Person
     {
         [Key]
         public int PersonId { get; set;}

         [MaxLength(5)]
         public string Salutation { get; set; }

         [MaxLength(50)]
         public string FirstName { get; set; }

         [MaxLength(50)]
         public string LastName { get; set; }

         [MaxLength(50)]
         public string Title { get; set; }

         [DataType(DataType.EmailAddress)]
         [MaxLength(254)]
         public string EmailAddress { get; set; }

         [DataType(DataType.MultilineText)]
         public string Biography { get; set; }     
     }
}

使用此自定义属性

namespace CustomViewTemplate
{
     [AttributeUsage(AttributeTargets.Property)]
     public class RichTextAttribute : Attribute
     {
         public RichTextAttribute() { }
     }
}

然后创建一个我们将在模板中引用的 T4Helper

using System; 

namespace CustomViewTemplate
{
     public static class T4Helpers
     {
         public static bool IsRichText(string viewDataTypeName, string propertyName)
         {
             bool isRichText = false;
             Attribute richText = null;
             Type typeModel = Type.GetType(viewDataTypeName);

             if (typeModel != null)
             {
                 richText = (RichTextAttribute)Attribute.GetCustomAttribute(typeModel.GetProperty(propertyName), typeof(RichTextAttribute));
                 return richText != null;
             }

             return isRichText;
         }
     }
}
于 2015-05-16T18:41:38.730 回答
4

所以,这就是你的做法。按照本教程了解如何创建自定义属性http://origin1tech.wordpress.com/2011/07/20/mvc-data-annotations-and-custom-attributes/

要在 T4 脚手架模板中读取此属性值,请首先按照此处所述添加模板文件http://www.hanselman.com/blog/ModifyingTheDefaultCodeGenerationscaffoldingTemplatesInASPNETMVC.aspx

然后,例如,从 AddView 文件夹中打开 List.tt。此模板创建索引视图。

转到模板文件的末尾并找到类 ModelProperty 的定义。将您的属性值添加到它( public string MyAttributeValue { get; set; }

现在在 List.tt 中往下走一点,找到 bool Scaffold(PropertyInfo property) 方法。您将需要添加自己的属性属性阅读器。对于上述教程,此方法将是:

string OptionalAttributesValueReader(PropertyInfo property){
    foreach (object attribute in property.GetCustomAttributes(true)) {
        var attr = attribute as OptionalAttributes ;
        if (attr != null) {
                return attr.style;
        }
    }
    return String.Empty;
}

然后在文件底部找到方法List GetEligibleProperties(Type type)。像这样将您的阅读器添加到其中:

            ...
            IsForeignKey = IsForeignKey(prop),
            IsReadOnly = prop.GetSetMethod() == null,
            Scaffold = Scaffold(prop),
            MyAttributeValue =  OptionalAttributesValueReader(prop)

当您想使用和阅读此属性时,您可以像在 List.tt 中使用 Scaffold 属性一样进行操作

      List<ModelProperty> properties = GetModelProperties(mvcHost.ViewDataType);
      foreach (ModelProperty property in properties) {
          if (property.MyAttributeValue != String.Empty) {
              //read the value
              <#= property.MyAttributeValue #>  
           }
       }

由于这些类是在我的项目中定义的,我必须将我的项目 dll 和命名空间添加到 List.tt 的顶部:

     <#@ assembly name="C:\myProjectPath\bin\myMVCproject.dll" #>
     <#@ import namespace="myMVCproject.CustomAttributes" #>

如果你的模型发生了变化,你需要在脚手架中找到这些新的变化,你需要重新构建你的项目。

希望任何寻找解决方案的人都会发现这很有用。请问有什么不清楚的地方。

于 2013-11-03T07:26:47.943 回答
2

这就是我在 MVC 5 中的做法。我很久以前就这样做了,我可能会忘记一些东西,我只是复制/粘贴我在修改后的模板中看到的内容。

我需要一种方法来设置(例如)创建/编辑视图或列表视图表中的属性顺序。所以我创建了一个OrderAttribute带有整数属性的自定义属性Order

为了在 T4 模板中访问这个属性,我修改了文件ModelMetadataFunctions.cs.include.t4. 在顶部,我添加了一个Order从对象中检索属性中设置的值的PropertyMetadata方法,以及另一种按该顺序简单地对PropertyMetadata项目列表进行排序的方法:

List<PropertyMetadata> GetOrderedProperties(List<PropertyMetadata> properties, Type modelType) {
    return properties.OrderBy<PropertyMetadata, int>(p => GetPropertyOrder(modelType, p)).ToList();
}

int GetPropertyOrder(Type type, PropertyMetadata property) {
    var info = type.GetProperty(property.PropertyName);
    if (info != null)
    {
        var attr = info.GetCustomAttribute<OrderAttribute>();
        if (attr != null) 
        {
            return attr.Order;
        }
    }
    return int.MaxValue;
}

最后,例如在 List 模板中,我添加了一个调用该GetOrderedProperties方法的部分:

var typeName = Assembly.CreateQualifiedName("AcCtc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", ViewDataTypeName);
var modelType = Type.GetType(typeName);

var properties = ModelMetadata.Properties.Where(p => p.Scaffold && !p.IsPrimaryKey && !p.IsForeignKey && !(p.IsAssociation && GetRelatedModelMetadata(p) == null)).ToList();
properties = GetOrderedProperties(properties, modelType);

foreach (var property in properties)
{
//...
}

不幸的是,我需要项目的名称才能创建我需要从中获取属性的 Type 对象。不理想,也许你可以通过其他方式得到它,但如果没有这个字符串,包括所有版本的东西,我就无法管理它。

于 2015-05-15T23:05:38.967 回答