我需要能够将DisplayAttribute应用于类,但它的AttributeUsage在当前的.NET / .NET核心版本中不允许这样做。它看起来像这个已对.NET Core vNext进行了补救,但是如果有某种方法可以忽略或覆盖这个限制,直到这个更改进入.NET发行版,这将是非常有帮助的。我能看到的唯一选择是重新实现整个过程(包括本地化),但我真的不想只为了在.NET vNext发布后立即支持和测试它。
有什么聪明的主意吗?
AttributeUsage限制是在运行时由CLR进行验证,还是仅仅是编译时间限制?如果只检查它们的编译时间,那么是否有一种聪明的方法可以将编译器使用的元数据“欺骗”到允许使用,或者以某种方式修改系统程序集,以便我的dev机器允许使用?
*我似乎不能编辑赏金描述,所以仅仅为了澄清,赏金的解决方案必须为.NET框架工作,.NET核心的加分也是如此。
发布于 2018-07-08 15:18:13
虽然您不应该更改现有的.NET程序集-由于签名和GAC (麻烦等待),但是可以在编译后将该属性添加到现有的类中,并且没有问题。AttributeUsage似乎没有在运行时强制执行。
因此,我创建了一个小Fody外接程序,它重写了DisplayAttribute的一个特定属性。
首先,我们的小虚拟属性将通过Fody重写:
[AttributeUsage (AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Method | AttributeTargets.Class)]
public class DisplayPatchAttribute : Attribute
{
public DisplayPatchAttribute()
{
}
}还有一个测试DisplayAttribute是否应用于测试类的虚拟程序。在没有Fody-addin的情况下运行时,它总是会打印"no“(注意,测试类使用的是我们的虚拟属性而不是真正的属性):
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代码):
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级别,所以它应该可以正常工作。
发布于 2018-07-07 06:49:17
我对AttributeTargets.Class进行了分解和添加并重新编译。我将名称空间更改为System.ComponentModel.MyDataAnnotations,以避免名称空间冲突。如果您需要更改名称空间或其他东西,我可以发送sln。
https://drive.google.com/open?id=1KR5OJwsOtGUdOBWIxBoXuDHuq4Nw-X7d
https://stackoverflow.com/questions/51095264
复制相似问题