C#:有没有办法访问当前字段的名称?

时间:2011-04-05 09:11:23

标签: c# reflection fieldinfo

在C#中,我定义了一个特定类的静态字段。在课堂上,我希望能够显示静态字段的名称,非常类似:

public class Unit {
  public string NameOfField { get { return ...; } }
}

public static Unit Hectare = new Unit();

如果我现在访问:

Hectare.NameOfField

我希望它返回:

Hectare

我知道有一个静态函数System.Reflection.MethodBase.GetCurrentMethod(),但据我所知,没有办法获取包含这个当前方法的实例的名称?

还有System.RuntimeFieldHandle结构,但我无法识别任何GetCurrentFieldHandle()方法。

我不确定我是否遗漏了一些明显的东西?

对此非常感谢。

4 个答案:

答案 0 :(得分:1)

您不应该依赖于开发中的变量名称,因为它们不会在运行时退出。

最好直接使用名称初始化Unit:

public class Unit {

  public Unit(string name)
  {
     NameOfField = name;
  }
  public string NameOfField { get; private set;} }
}

public static Unit Hectare = new Unit("Hectare");

答案 1 :(得分:0)

只有这样才能将这些信息存储在课堂上:

public static Unit Hectare = new Unit("Hectare");

编译代码时,所有变量名都会丢失并被内部引用替换。没有办法再次获得该名称。

答案 2 :(得分:0)

您可以使用Reflection获取类字段和属性。如下所示:

假设你有一个属性的类:

class Test
{
    public static string MySupperField
    {
        get
        {
            return "Some symbols here";
        }
    }
}

......

您可以通过以下方式阅读属性名称:

public string[] GetClassStaticNames(Type T)
{
    string[] names;

    System.Reflection.PropertyInfo[] props = T.GetProperties(); // This will return only properties not fields! For fields obtaining use T.GetFields();

    names = new string[props.Count()];
    for (int i = 0; i < props.Count(); i++)
    {
        names[i] = props[i].Name;
    }

    return names;
}

希望这会有所帮助。

<强> [编辑]
回到你的问题 - 不,你不能获得当前变量的名称 你所要求的是因为类性质而无法完成,它们是内存中的对象,并且对一个对象的引用可以保存在许多变量中,当你请求实例字段或属性的值时,它实际上将在对象中执行操作没有变量的内存保存对该对象的引用。因此获取变量的名称保持对当前实例的引用没有意义

答案 3 :(得分:0)

感谢所有花时间回答和讨论我的问题的人。

为了让您知道,我已经实施了足以满足我需求的解决方案。解决方案不是一般的,它有一些陷阱,但我想我无论如何都要分享它,以防它对其他人有帮助。

原则上,定义字段时使用的类如下所示:

public class Unit : IUnit {
  public NameOfField { get; set; }
  ...
}

如您所见,该类实现了IUnit接口,并且我在NameOfField属性中提供了一个公共setter。

静态字段通常在某些包含类中定义如下:

public static Unit Hectare = new Unit();

我的解决方案是在实现中使用字段之前通过反射设置NameOfField属性。 我通过静态构造函数执行此操作(当然需要在访问Unit字段之前调用它)。 我使用Linq来遍历相关字段的执行程序集,当我检测到这些字段(类型实现IUnit接口的字段)时,我使用Any扩展方法为每个字段设置NameOfField属性:

Assembly.GetExecutingAssembly().GetTypes().
  SelectMany(type => type.GetFields(BindingFlags.Public | BindingFlags.Static)).
  Where(fieldInfo => fieldInfo.FieldType.GetInterfaces().Contains(typeof(IUnit))).
  Any(fieldInfo =>
  {
    ((IUnit)fieldInfo.GetValue(null)).NameOfField= fieldInfo.Name;
    return false;
  });

这种方法存在一些缺点:

  • 在访问任何单位字段之前,必须通过手动干预调用静态构造函数
  • NameOfField setter是公共的。在我的情况下,这没有问题,但可能在其他情况下应用。 (我假设可以将setter设为私有并通过进一步反射来调用,但我还没有花时间进一步探索这条路径。)
  • ......?

无论哪种方式,也许这个解决方案对我以外的其他人都有帮助。