获取一个只给出类名的类属性名

时间:2014-07-02 03:59:34

标签: c#

我想知道类的所有属性的名称,只给出类名。 看起来应该是这样的:

public object GetClassAttribute(string className)

实施例

鉴于这两个类:

public class PersonItem
    {
       public string Name {get;set;}
       public string LastName   {get;set;}
       public byte Age   {get;set;}
    }

public class DepartmentItem
        {
           public string DepartmentName {get;set;}
           public string Office  {get;set;}
           public string Address   {get;set;}
        }

该功能应该是这样的:

var ListAttribute= GetClassAttribute(Person);

// returns:
// ListAttribute[0] "Name"
// ListAttribute[1] "LastName"
// ListAttribute[2] "Age

var ListAttribute= GetClassAttribute(DepartmentItem);
// returns:
// ListAttribute[0] "DepartmentName "
// ListAttribute[1] "Office  "
// ListAttribute[2] "Address   

3 个答案:

答案 0 :(得分:3)

我想你想反思一种类型。你问的问题可以像这样查询:

public static IEnumerable<string> FieldsOf(string className)
{
    var asm = Assembly.GetCallingAssembly();
    var type = asm.GetTypes().Single(t => t.Name == className);
    var fields = type.GetFields();
    return fields.Select(f => f.Name);
}

此函数首先获取它的调用程序集,然后搜索具有给定名称的唯一类 - 您必须这样做,因为通常使用Assembly.GetType(fullName)按名称搜索全名(包括它的名称空间),但示例你给了没有。 如果您有多个具有相同名称的类(例如,不同的名称空间),则可能会失败!

最后它获取所有字段并返回其名称。 这也找不到属性! (您必须使用GetProperties搜索它们,并且您可能希望控制字段的找到方式 - 例如没有私有等等。所有这些都可以通过检查字段属性或提供更多参数来控制到GetFields

顺便说一下:你的班级定义也是错误的 - 每行后都有;个缺失:

public class PersonItem
{
    public string Name;
    public string LastName;
    public byte Age;
}

您可以打印它的字段:

foreach (var f in FieldsOf("PersonItem"))
    Console.WriteLine(f);

获取实例的那些字段的值:

我想迟早你也需要这些值 - 这里是上述方法的扩展,展示了你如何做到这一点:

public static IEnumerable<Tuple<string, Func<object, object>>> FieldsOf(string className)
{
    var asm = Assembly.GetCallingAssembly();
    var type = asm.GetTypes().Single(t => t.Name == className);
    var fields = type.GetFields();

    return fields.Select(f => Tuple.Create<string, Func<object, object>>(f.Name, f.GetValue));
}

这个返回元组中字段的NameGetter(对于这个例子来说足够了 - 通常你应该使用一个结构或名称比Item1更好的东西和{ {1}}关于它的属性)。

以下是一个例子:

Item2

这将提供此输出:

Object person = new PersonItem {Name = "John", LastName = "Smith", Age = 33};

foreach (var f in FieldsOf("PersonItem"))
    Console.WriteLine("Fieldname: {0} - Value: {1}", f.Item1, f.Item2(person));

包含属性

由于您现在更改了问题,以便您使用的类只有属性(而不是字段) - 您还需要包含这些:

Fieldname: Name - Value: John
Fieldname: LastName - Value: Smith
Fieldname: Age - Value: 33

注意:此代码只会获取不使用索引的属性(如您所述) - 这是部分public static IEnumerable<Tuple<string, Func<object, object>>> FieldsOf(string className) { var asm = Assembly.GetCallingAssembly(); var type = asm.GetTypes().Single(t => t.Name == className); var fields = type.GetFields(); var properties = type.GetProperties(); return fields.Select(f => Tuple.Create<string, Func<object, object>>(f.Name, f.GetValue)) .Concat(properties.Select(p => Tuple.Create<string, Func<object, object>>(p.Name, o => p.GetValue(o, null)))); } - o => p.GetValue(o, null)是索引所需的位置如果你也需要那些。

使用null代替type-name

Amir提出了一个很好的观点:你也可以使用这些类型。

如果您在编译时不知道对象类型,那么这个很好:

Type

示例:

public static IEnumerable<Tuple<string, Func<object, object>>> FieldsOf(Type type)
{
    var fields = type.GetFields();
    var properties = type.GetProperties();

    return
        fields.Select(f => Tuple.Create<string, Func<object, object>>(f.Name, f.GetValue))
        .Concat(properties.Select(p => Tuple.Create<string, Func<object, object>>(p.Name, o => p.GetValue(o, null))));
}

使用泛型而不是类型名称

这是一个通用版本 - 如果您在编译时知道类型,那么这个版本很好:

Object person = new PersonItem {Name = "John", LastName = "Smith", Age = 33};

foreach (var f in FieldsOf(person.GetType()))
    Console.WriteLine("Fieldname: {0} - Value: {1}", f.Item1, f.Item2(person));

Console.ReadLine();

示例:

public static IEnumerable<Tuple<string, Func<T, object>>> FieldsOf<T>()
{
    var type = typeof (T);
    var fields = type.GetFields();
    var properties = type.GetProperties();

    return
        fields.Select(f => Tuple.Create<string, Func<T, object>>(f.Name, o => f.GetValue(o)))
        .Concat(properties.Select(p => Tuple.Create<string, Func<T, object>>(p.Name, o => p.GetValue((T)o, null))));
}

答案 1 :(得分:1)

上面的两个答案很棒,但是你问了一个特定的属性问题,所以这里是一个&#34;复制粘贴&#34;回答:

    public IEnumerable<string> GetPropertyNames(Type type)
    {
        return type.GetProperties().Select(p => p.Name);
    }

用法:

   var personItemProps = GetPropertyNames(typeof(PersonItem)).ToList();
   var departmentItemProps = GetPropertyNames(typeof(DepartmentItem)).ToList();

您也可以使用&#34; Type&#34;:

上的扩展功能执行此操作
    public static class TypeExtensions
    {
       public static IEnumerable<string> GetPropertyNames(this Type type)
       {
           return type.GetProperties().Select(p => p.Name);
       }
    }

用法:

    var personItemProps = typeof(PersonItem).GetPropertyNames().ToList();
    var departmentItemProps = typeof(DepartmentItem).GetPropertyNames().ToList();

如果您不需要IEnumerables,那么只需更改函数以返回List。

答案 2 :(得分:0)

您可以从类名(字符串)获取属性列表,首先使用Type.GetType将字符串转换为Type。获得类型后,可以调用GetFields()来获取属性。

方法定义

public IEnumerable<string> GetClassAttribute(string className)
{
    Type t = Type.GetType(className);
    return t.GetFields().Select(f=>f.Name);
}

方法调用

var attributes = GetClassAttribute("ClassNamespace.PersonItem");

注意您需要按照MSDN文档中的说明为您的类提供命名空间。

Type GetType(string typeName)

  

typeName类型:System.String类型的程序集限定名称   要得到。请参阅AssemblyQualifiedName。如果类型在当前   执行程序集或在Mscorlib.dll中,它足以提供   类型名称由其命名空间限定。