首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >忽略/重写AttributeUsage限制

忽略/重写AttributeUsage限制
EN

Stack Overflow用户
提问于 2018-06-29 06:07:18
回答 2查看 431关注 0票数 8

我需要能够将DisplayAttribute应用于类,但它的AttributeUsage在当前的.NET / .NET核心版本中不允许这样做。它看起来像这个已对.NET Core vNext进行了补救,但是如果有某种方法可以忽略或覆盖这个限制,直到这个更改进入.NET发行版,这将是非常有帮助的。我能看到的唯一选择是重新实现整个过程(包括本地化),但我真的不想只为了在.NET vNext发布后立即支持和测试它。

有什么聪明的主意吗?

AttributeUsage限制是在运行时由CLR进行验证,还是仅仅是编译时间限制?如果只检查它们的编译时间,那么是否有一种聪明的方法可以将编译器使用的元数据“欺骗”到允许使用,或者以某种方式修改系统程序集,以便我的dev机器允许使用?

*我似乎不能编辑赏金描述,所以仅仅为了澄清,赏金的解决方案必须为.NET框架工作,.NET核心的加分也是如此。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-08 15:18:13

虽然您不应该更改现有的.NET程序集-由于签名和GAC (麻烦等待),但是可以在编译后将该属性添加到现有的类中,并且没有问题。AttributeUsage似乎没有在运行时强制执行。

因此,我创建了一个小Fody外接程序,它重写了DisplayAttribute的一个特定属性。

首先,我们的小虚拟属性将通过Fody重写:

代码语言:javascript
复制
[AttributeUsage (AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Class)]
public class DisplayPatchAttribute : Attribute
{
  public DisplayPatchAttribute()
  {
  }
}

还有一个测试DisplayAttribute是否应用于测试类的虚拟程序。在没有Fody-addin的情况下运行时,它总是会打印"no“(注意,测试类使用的是我们的虚拟属性而不是真正的属性):

代码语言:javascript
复制
internal static class Program
{
  private static void Main (string[] args)
  {
    var attr = Attribute.GetCustomAttribute (typeof(Test), typeof(DisplayAttribute)) as DisplayAttribute;
    Console.WriteLine (attr == null ? "no" : "yes");
  }
}

[DisplayPatch]
internal class Test
{
}

现在,我们添加了一个小的Fody编织器,它将属性重写到真正的属性(传入的hacky代码):

代码语言:javascript
复制
public class DisplayAttributeWeaver : BaseModuleWeaver
{
  public override void Execute()
  {
    var dataAnnotationAssembly = ModuleDefinition.AssemblyReferences.First (e => e.Name.Contains ("DataAnnotation"));
    var resolvedDataAnnotationAssembly = ModuleDefinition.AssemblyResolver.Resolve (dataAnnotationAssembly);
    var displayAttribute = resolvedDataAnnotationAssembly.Modules.First().GetType ("System.ComponentModel.DataAnnotations.DisplayAttribute");
    var displayAttributeConstructor = ModuleDefinition.ImportReference(displayAttribute.GetConstructors().First());

    foreach (var type in ModuleDefinition.Types)
    {
      var targetAttribute = type.CustomAttributes.FirstOrDefault (e => e.AttributeType.Name == "DisplayPatchAttribute");
      if (targetAttribute == null)
        continue;

      type.CustomAttributes.Remove (targetAttribute);

      var newAttr = new CustomAttribute (displayAttributeConstructor);
      type.CustomAttributes.Add (newAttr);
    }
  }

  public override IEnumerable<string> GetAssembliesForScanning()
  {
    yield return "mscorlib";
    yield return "System";
  }
}

它将DisplayPatchAttribute转换为DisplayAttribute,因此程序输出“是”。

然后,DisplayPatchAttribute看起来像普通的DisplayAttribute,并将其属性复制到新属性中。

虽然没有对.NET内核进行测试,但由于Fody支持net,并且修复程序处于IL级别,所以它应该可以正常工作。

票数 1
EN

Stack Overflow用户

发布于 2018-07-07 06:49:17

我对AttributeTargets.Class进行了分解和添加并重新编译。我将名称空间更改为System.ComponentModel.MyDataAnnotations,以避免名称空间冲突。如果您需要更改名称空间或其他东西,我可以发送sln。

https://drive.google.com/open?id=1KR5OJwsOtGUdOBWIxBoXuDHuq4Nw-X7d

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51095264

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档