【问题标题】:Get custom attribute from specific object property/field从特定对象属性/字段获取自定义属性
【发布时间】:2014-04-27 21:15:37
【问题描述】:

我已经搜索了一段时间并测试了几种方法,但我没有找到我正在寻找的答案。我会尽力解释。

我有一个包含多个字段/属性的对象。这些属性具有自定义属性。 我想要的是在不了解对象的所有知识的情况下从特定属性中获取自定义属性。

是基类

// FieldAttr has a public Text propery

public class TestObject  
{
    // Declare fields
    [FieldAttr("prop_testfld1")]
    public FLDtype1 testfld1 = new FLDtype1();

    [FieldAttr("prop_testfld2")]
    public FLDtype2 testfld2 = new FLDtype2();

    [FieldAttr("prop_testfld3")]
    public FLDtype1 testfld3;
}

public class FLDtype1
{
    public string Value { get; set; }
}

public class FLDtype2
{
    public Guid Value { get; set; }
}

public sealed class FieldAttr: System.Attribute
{
    private string _txt;

    public EntityFieldType(string txt)
    {
        this._text = txt;
    }

    public string Text { get { return this._text; } }
}

我希望能够在我的应用程序中执行此操作:

static void Main(string[] args)
{
    TestObject test = new TestObject();

    // (Option 1: preferred)
    Console.WriteLine(test.testfld1.getFieldAttr().Text);

    // (Option 2)
    Console.WriteLine(test.getFieldAttr(test.testfld1).Text);
}

这可能吗?我已经看到了从对象的所有属性/字段获取自定义属性值的方法,但不是针对特定字段。

我有一种工作方法可以从枚举中获取自定义属性,但无法为对象字段/属性重新创建它。这是因为我无法获得我试图探索的字段的名称,因为(例如)test.testfld1.ToString() 给了我“ns.FLDtype1”。

期待答案:) (请原谅我的英语)

【问题讨论】:

  • 你试过这种方式吗? link
  • 是的。问题是 GetMethod("")/GetField("") 需要字段的字符串名称。我无法理解。
  • 我不想透露姓名。我希望该字段返回自己的自定义属性。如果我能做到这一点,我可以创建一种更加动态的方式来处理这些字段。给定的示例是我想要做的简单表示。

标签: c# properties field custom-attributes


【解决方案1】:

是的,有可能:

public static class Extensions
{
    public static FieldAttr GetFieldAttr(
        this TestObject source,
        Expression<Func<TestObject,object>> field)
    {
        var member = field.Body as MemberExpression;
        if (member == null) return null; // or throw exception

        var fieldName = member.Member.Name;

        var test = typeof (TestObject);
        var fieldType = test.GetField(fieldName);
        if (fieldType != null)
        {
            var attribute = fieldType.GetCustomAttribute<FieldAttr>();

            return attribute;
        }

        return null;
    }
}

用法:

TestObject test = new TestObject();

var attr = test.GetFieldAttr(x => x.testfld3);

if(attr != null) Console.WriteLine(attr.Text);

这里是fiddle

【讨论】:

  • 如果我只声明一个 FLDtype1 类型的字段/属性,则此方法有效。如果我声明 2,我每次只得到第一个。在小提琴中, Console.WriteLine(test.testfld3.GetFieldAttr().Text) 返回“prop_testfld1”,而它应该返回“prop_testfld3”
  • 这是我卡住的地方
  • @user2916010 啊,你是对的。对不起,我刚刚更新了我的答案。再试一次。我也更新了fiddle
  • 也试过这个,但我正在努力让它更聪明。这种调整意味着我不能从字段本身调用 getFieldAttr。 (test.testfld3.getFieldAttr())。
【解决方案2】:

经过一天的反复试验,我决定使用 Selman22 答案并稍作修改。这是我创建的代码:

public class TestObject : iTestObject 
{
    // Declare fields
    [FieldAttr("prop_testfld1")]
    public FLDtype1 testfld1 = new FLDtype1();

    [FieldAttr("prop_testfld2")]
    public FLDtype2 testfld2 = new FLDtype2();

    [FieldAttr("prop_testfld3")]
    public FLDtype1 testfld3;
}

public class FLDtype1 : iField
{
    public string Value { get; set; }
}

public class FLDtype2 : iField
{
    public Guid Value { get; set; }
}

public sealed class FieldAttr: System.Attribute
{
    private string _txt;

    public FieldAttr(string txt)
    {
        this._txt = txt;
    }

    public string Text { get { return this._txt; } }
}

public interface iField { }
public interface iTestObject { }

public static class Extensions
{
    public static FieldAttr GetFieldAttr<T>(this T source, Expression<Func<iField>> field) where T : iTestObject 
    {
        // Get member body. If no body present, return null
        MemberExpression member = (MemberExpression)field.Body;
        if (member == null) { return null; }

        // Get field info. If no field info present, return null
        FieldInfo fieldType = typeof(T).GetField(member.Member.Name);
        if (fieldType == null) { return null; }

        // Return custom attribute
        return fieldType.GetCustomAttribute<FieldAttr>();
    }
}

用法:

public class Program
{
    public static void Main()
    {
        TestObject test = new TestObject();
        Console.WriteLine(test.GetFieldAttr(() => test.testfld1).Text);
        Console.WriteLine(test.GetFieldAttr(() => test.testfld2).Text);
        Console.WriteLine(test.GetFieldAttr(() => test.testfld3).Text);
    }
}

用途:

using System;
using System.Linq;
using System.Reflection;
using System.Linq.Expressions;

我已经实现了接口来保护 GetFieldAttr 方法

@Sulman22:谢谢回复!

【讨论】:

  • 我想在@user2916010 的答案中添加的一件事是,有时您会遇到此异常:无法将“System.Linq.Expressions.UnaryExpression”类型的对象转换为“System”类型.Linq.Expressions.MemberExpression'。所以在使用这个解决方案之前,请先看看这篇文章,了解访问会员正文的正确方法:stackoverflow.com/questions/12420466/…
猜你喜欢
  • 2012-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多