【问题标题】:Get member to which attribute was applied from inside attribute constructor?获取从内部属性构造函数应用到哪个属性的成员?
【发布时间】:2021-01-14 07:06:16
【问题描述】:

我有一个自定义属性,在我的自定义属性的构造函数中我想将我的属性的属性值设置为我的属性应用到的属性的类型,有没有办法访问该属性的成员是从我的属性类内部应用的?

【问题讨论】:

  • 你能简单描述一下用例吗?
  • 如果您可以为您正在解决的问题提供更多详细信息,则可以提供替代解决方案。
  • 谢谢,我知道如何以不同的方式实现相同的目标,但我想知道这是否可行,因为代码会更简洁。

标签: c# .net reflection attributes


【解决方案1】:

恐怕属性不是这样工作的。它们只是“标记”,附着在对象上,但无法与之交互。

属性本身通常应该没有行为,只包含它们所附加的类型的元数据。任何与属性相关的行为都应该由另一个类提供,该类会寻找该属性的存在并执行一项任务。

如果您对该属性所应用的类型感兴趣,则该信息将在您反映以获取该属性的同时可用。

【讨论】:

  • 正如您所说,这不是世界末日,因为您在通过反射获取自定义属性时知道类型,但如果传递给 GetCustomAttribute 的类型也存储在System.Attribute
【解决方案2】:

.NET 4.5 可以使用CallerMemberName

[SomethingCustom]
public string MyProperty { get; set; }

那么你的属性:

[AttributeUsage(AttributeTargets.Property)]
public class SomethingCustomAttribute : Attribute
{
    public StartupArgumentAttribute([CallerMemberName] string propName = null)
    {
        // propName == "MyProperty"
    }
}

【讨论】:

  • 这应该是现在标记的答案!正是我需要的,谢谢!
  • 这是前段时间添加的,但我有一个后续问题:根据此链接 [docs.microsoft.com/en-us/dotnet/csharp/programming-guide/… [CallerMemberName] 只给你会员名称,而不是完全限定的方式。那么如果我想通过反射得到那个类型,我怎么知道它的全名呢?
【解决方案3】:

你可以做下一步。这是一个简单的例子。

//target class
public class SomeClass{

    [CustomRequired(ErrorMessage = "{0} is required", ProperytName = "DisplayName")]
    public string Link { get; set; }

    public string DisplayName { get; set; }
}
    //custom attribute
    public class CustomRequiredAttribute : RequiredAttribute, IClientValidatable
{
    public string ProperytName { get; set; }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var propertyValue = "Value";
        var parentMetaData = ModelMetadataProviders.Current
             .GetMetadataForProperties(context.Controller.ViewData.Model, context.Controller.ViewData.Model.GetType());
        var property = parentMetaData.FirstOrDefault(p => p.PropertyName == ProperytName);
        if (property != null)
            propertyValue = property.Model.ToString();

        yield return new ModelClientValidationRule
        {
            ErrorMessage = string.Format(ErrorMessage, propertyValue),
            ValidationType = "required"
        };
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-03
    • 1970-01-01
    • 2014-09-13
    • 2022-12-16
    • 2023-03-21
    • 2016-01-31
    相关资源
    最近更新 更多