从指定的非静态类(C#)获取所有属性、其数据类型、值和名称

问题描述 投票:0回答:2

我们有一个这样的(测试)课程:

class Animal
{
    public string AnimalName { get; set; }
    public string AnimalType { get; set; }
    public int AnimalAgeInMonths { get; set; }
}

...以及类的对象(或引用):

Animal animal = new Animal();
animal.AnimalName = null; // No name yet
animal.AnimalType = "Sheep";
animal.AnimalAgeInMonths = 7;

所以我需要一个返回

System.Collections.Generic.List<(string[], string[], string[])>
的方法。第一个字符串数组表示所有属性的名称(即
AnimalName
AnimalType
等),第二个数组 - 值(即 null
Sheep
等),第三个数组 - 数据类型,例如:

  • System.Int32
    对于
    int
  • System.Single
    对于
    float
  • System.String
    对于
    string
  • 等等

(可以使用

typeof
关键字生成)。

所以总的来说,我需要这样的方法:

public List<(string[], string[], string[])> GetClassPropertyInfo(object Class)

可以这样调用:

GetClassPropertyInfo(animal);

我尝试过这个(第四次尝试):

using System;
using System.Reflection;
using System.Collections.Generic;

namespace TestAttempt
{
    public class Animal
    {
        public string AnimalName { get; set; }
        public string AnimalType { get; set; }
        public int AnimalAgeInMonths { get; set; }
    }
    
    public class Program
    {
        static void Main()
        {
            Animal a = new Animal();
            a.AnimalName = "";
            a.AnimalType = "Sheep";
            a.AnimalAgeInMonths = 7;
            
            List<(string[], string[], string[])> types = new Program().GetClassPropertyInfo(a, typeof(Animal));
            
            foreach (var Iteration in types)
            {
                for (int i = 0; i < Iteration.Item1.Length; i++)
                {
                    Console.WriteLine($"{Iteration.Item3[i]} {Iteration.Item1[i]} = {Iteration.Item2[i]}");
                }
            }
        }
        
        private List<(string[], string[], string[])> GetClassPropertyInfo(object Class, Type _Class)
        {
            var @return = new List<(string[], string[], string[])>();
            
            List<string> propertyNames = new List<string>();
            List<string> propertyTypes = new List<string>();
            List<string> propertyValues = new List<string>();
            
            // https://stackoverflow.com/questions/737151/how-to-get-the-list-of-properties-of-a-class
            foreach (var prop in Class.GetType().GetProperties())
            {
                propertyNames.Add(Convert.ToString(prop.Name));
                propertyValues.Add(Convert.ToString(prop.GetValue(Class, null)));
            }
            
            // System.Reflection.FieldInfo
            // See: https://learn.microsoft.com/en-us/dotnet/api/system.reflection.fieldinfo?view=net-7.0
            FieldInfo[] fi = _Class.GetFields(BindingFlags.NonPublic | BindingFlags.Instance
            | BindingFlags.Public);
            
            for (int i = 0; i < fi.Length; i++)
                propertyTypes.Add(Convert.ToString(fi[i].FieldType));
                
            @return.Add((propertyNames.ToArray(), propertyValues.ToArray(), propertyTypes.ToArray()));
            
            return @return;
        }
    }
}

它可以工作,但当数组是属性时则不行。

致以诚挚的问候,
-winscripter。

c# .net class properties
2个回答
0
投票

以下将获取每个属性的名称、类型和值(作为字符串) - 您可以使用它作为起点。然后,您可以将名称、类型和值存储在您需要的任何结构中并返回它。希望有帮助。

using System;
using System.Collections;
using System.Reflection;

class Animal
{
    public string AnimalName { get; set; }
    public string AnimalType { get; set; }
    public int AnimalAgeInMonths { get; set; }
    public int[] array { get; set; } 
}

class Program
{
    static void Main()
    {

        Animal animal = new Animal();
        animal.AnimalName = null; // No name yet
        animal.AnimalType = "Sheep";
        animal.AnimalAgeInMonths = 7;
        animal.array = new int[] { 1, 3, 5, 7, 9 };
        
        class_info( animal );
            
    }
    
    static void class_info(object Class)
    {
        String val;
        
        foreach (PropertyInfo propertyInfo in Class.GetType().GetProperties())
        {
            // Property Name ...
            Console.WriteLine( propertyInfo.Name );

            // Property type (as string) ...
            Console.WriteLine( propertyInfo.PropertyType.ToString() );

            // Property value (as string) ...
            if ( propertyInfo.GetValue(Class, null) is null ) 
            {
                val = "null";
                Console.WriteLine( val );
            }
            else
            {
                // Property is an array, show values (as strings) ...
                if (propertyInfo.PropertyType.IsArray)
                {

                    IEnumerable array = propertyInfo.GetValue( Class, null ) as IEnumerable;

                    if ( array is null )
                    {
                        Console.WriteLine( "Array is null" );
                    }
                    else
                    {
                        Console.WriteLine("Array values");
                        Console.WriteLine("------------");

                        foreach (var element in array)
                            Console.WriteLine(element.ToString());
                    }

                }
                else
                {
                   val = propertyInfo.GetValue(Class, null).ToString();
                   Console.WriteLine( val );
                }
            }

        }  
        
    }
    
}

0
投票

看起来你只想要 3 个数组。其中每一个都可以通过 Reflection API 轻松获得。

static (string[], string?[], string[]) GetClassPropertyInfo(object o) {
    // pass binding flags here if you want a different set of properties than default behaviour
    var properties = o.GetType().GetProperties();
    return (
        properties.Select(x => x.Name).ToArray(),
        properties.Select(x => x.GetValue(o)?.ToString()).ToArray(),
        properties.Select(x => x.PropertyType.Name).ToArray()
    );
}

关于第二个数组 - 您需要一种方法将任何属性值(包括

null
)转换为
string
。这里我刚刚调用了
ToString
,如果值为
null
,结果也是null。这就是为什么第二个数组具有可为 null 的元素,并且类型为
string?[]

关于第三个数组,

Name
返回简单名称,不带名称空间。如果您需要这样做,您可能需要改为
x.PropertyType.FullName ?? x.PropertyType.Name
,或者只是
x.PropertyType.ToString()

另请注意,您完全可以在 tuple 中返回 3 个内容,就像我在这里所做的那样,而不用将它们放入列表中。

也就是说,我建议为此创建一个 record 类型:

record ObjectInfo(string[] Name, string?[] Values, string[] Types);

你可以写:

return new ObjectInfo(
    ...
);

还要考虑也许它们不应该都是字符串。我认为这更有意义:

record ObjectInfo(string[] Name, object?[] Values, Type[] Types);
© www.soinside.com 2019 - 2024. All rights reserved.