c# - 访问 T4 模板中的自定义属性 (VS2012 MVC4)

标签 c# asp.net-mvc-4 reflection data-annotations t4

我正在尝试访问我的自定义属性,例如 SortableAttribute附加到我正在编写的 T4 Controller 模板中的模型属性。我已从 List.tt 中复制了类 block 、程序集和导入作为样板。

首先,我尝试按如下方式强制转换属性:

<#+
string SortableBy(PropertyInfo property)
{
    foreach (object attribute in property.GetCustomAttributes(true))
    {
        var sortable = attribute as SortableAttribute;
        if (sortable != null) return sortable.By == "" ? property.Name : sortable.By;
    }
    return property.Name;
}
#>

然而,这没有产生积极的结果,因为 T4 不知道我的项目的命名空间。为了解决这个问题,我添加了项目的 dll 并导入了所需的命名空间。

<#@ assembly name ="c:\path\to\MyProject\bin\MyProject.dll" #>
<#@ import namespace= "MyProject.Filters" #>

一开始似乎很成功(例如,命名空间导入没有错误),但它仍然没有找到我的属性。如果我更换SortableAttributeMyProject.Filters.SortableAttribute ,错误消息是 SortableAttribute未在 MyProject.Filters 中找到.

为了解决这个问题,我对代码进行了如下更改:

<#+
string SortableBy(PropertyInfo property)
{
    foreach (object attribute in property.GetCustomAttributes(true))
    {
        if (attribute != null && attribute.GetType().Name == "SortableAttribute")
        {
            var sortableBy = (string) attribute.GetType().GetProperty("By").GetValue(attribute, null);
            return sortableBy == "" ? property.Name : sortableBy;
        }
    }
    return property.Name;
}
#>

我以为我中了大奖,但我很快就意识到property.GetCustomAttributes(true)返回所有属性,但不是我的...

示例模型:

public class MyModel
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    [Display(Name = "Full Name")]
    [Sortable]
    public int Name { get; set; }
}

实现SortableAttribute :

using System;

namespace MyProject.Filters
{
    [AttributeUsage(AttributeTargets.Property)]
    public class SortableAttribute : Attribute
    {
        public SortableAttribute(string by = "")
        {
            this.By = by;
        }

        public string By { get; private set; }
    }
}

你能指出我正确的方向吗?

非常感谢任何帮助!

编辑:

事实证明property.GetCustomAttributes(true)确实返回我的属性,但 SortableBy 中的以下表达式始终计算为 null :

(string) attribute.GetType().GetProperty("By").GetValue(attribute, null);

知道为什么会这样吗?

最佳答案

记住:构建可以解决很多问题,但是REBUILD可以解决所有问题!

为了回顾并帮助其他人编写 T4 模板,以下是一些可用作样板的工作代码:

读取 .tt 文件中的自定义属性(基于任何默认 View 模板中的 Scaffold()):

<#+
string SortableBy(PropertyInfo property)
{
    foreach (object attribute in property.GetCustomAttributes(true))
    {
        var sortable = attribute as SortableAttribute;
        if (sortable != null) return sortable.By == "" ? property.Name : sortable.By;
    }
    return property.Name;
}
#>

型号:

public class MyModel
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    [Display(Name = "Full Name")]
    [Sortable]
    public int Name { get; set; }
}

SortableAttribute 的实现:

using System;

namespace MyProject.Filters
{
    [AttributeUsage(AttributeTargets.Property)]
    public class SortableAttribute : Attribute
    {
        public SortableAttribute(string by = "")
        {
            this.By = by;
        }

        public string By { get; private set; }
    }
}

关于c# - 访问 T4 模板中的自定义属性 (VS2012 MVC4),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21414686/

相关文章:

c# - 从 Controller MVC 4 访问 UserProfile

java - 无法在运行时设置 SolrDocument 注释

c# - 使用 C# 获取 Int/short/byte 结构字节表示

c# 锁定并监听 CancellationToken

c# - 是否有不依赖于 IDisposable 的 Using 模式?

c# - 在 C# 中的 MS Word 文档的不同页面添加形状

jquery - 如何在asp.net MVC 4中通过ajax请求下载文件

c# - 在处理循环期间更新 ASP.NET UpdatePanel

asp.net-mvc-4 - 选择列表操作将 2 个集合合并到一个列表中

c# - 为什么通用类型定义实现的接口(interface)会丢失类型信息?