c#,创建类字段的集合

本文关键字:集合 字段 创建 | 更新日期: 2023-09-27 18:14:18

是否有一种方法来收集现有的类字段?

我有一个类,有很多不同类型的字段/属性,它们的名字有意义。

class ExampleClass
{
   public string meaningfulName1 { get; set;}
   public double meaningfulName2 { get; set;}
   ...
   public myOtherClass meaningfulNameN { get; set;}
}

我需要从外部(不是我的)程序生成的文件中读取这些属性的值。

由于有很多字段/属性,读取值并逐个赋值似乎效率低下。所以我想要这些字段/属性的集合。就像

foreach (fieldReference in ExampleClass.fieldReferenceCollection)
{
   readValueFromFile(fieldReference);
} 

但是我如何在保留所有名字的情况下创建一个呢?

用所有的参数值而不是单独的字段创建一个集合似乎是合乎逻辑的,但是字段名会丢失。而且,考虑到字段的数量,我们希望尽可能保留这些名称,以简化进一步的开发。

所以我需要单独的字段/属性和他们的集合在同一时间可用。

字典集合不是非常快,所以参数名作为值的键似乎也不完全合适。

我发现的另一个选项是反射,但我还不确定如何确定反射集合中字段的顺序。字段的顺序是非常重要的文件,我从读取值,没有元数据,只是一个十六进制值的序列。另外,对于从文件中读取值来说,反射似乎是多余的,而且它也很慢。

那么问题是:为了同时拥有类字段和它们的集合,我应该做些什么?

我对这个任务的假设是错误的吗?有没有其他的方法可以从文件中读取大量愚蠢的值到一个复杂的对象中?

注:我的第一个SO问题,英语是我的第二语言,所以我为错误感到抱歉。

c#,创建类字段的集合

似乎您必须使用反射来做您想要的。至于确定字段的顺序,我建议使用自定义属性标记属性。

这里有一个例子。希望这篇文章能让你找到你需要的解决方案。

namespace ConsoleApplication2
{
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public sealed class FileField : Attribute
    {
        public int Index { get; set; }
        public FileField() { }
    }
    class ExampleClass
    {
        [FileField(Index = 0)]
        public string meaningfulName1 { get; set; }
        [FileField(Index = 2)]
        public double meaningfulName2 { get; set; }
        [FileField(Index = 1)]
        public MyOtherClass meaningfulNameN { get; set; }
    }
    class MyOtherClass
    {
        public string Something { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var exampleClassFieldProperties = GetExampleClassFieldProperties();
            var lines = File.ReadAllLines("datafile.txt");
            var records = new List<ExampleClass>();
            foreach (var line in lines)
            {
                var fields = line.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                var record = new ExampleClass();
                for(int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++)
                {
                    if (exampleClassFieldProperties.ContainsKey(fieldIndex))
                    {
                        ReadValueFromFile(fields[fieldIndex], exampleClassFieldProperties[fieldIndex], record);
                    }
                }
                records.Add(record);
            }
            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
        }
        public static Dictionary<int, PropertyInfo> GetExampleClassFieldProperties()
        {
            var exampleClassFieldProperties = new Dictionary<int, PropertyInfo>();
            var properties = typeof(ExampleClass).GetProperties();
            foreach (var property in properties)
            {
                var attributes = property.GetCustomAttributes(false);
                int index = 0;
                foreach (var attribute in attributes)
                {
                    if (attribute is FileField)
                    {
                        index = ((FileField)attribute).Index;
                        if (exampleClassFieldProperties.ContainsKey(index) == false)
                        {
                            exampleClassFieldProperties.Add(index, property);
                        }
                    }
                }
            }
            return exampleClassFieldProperties;
        }
        public static void ReadValueFromFile(string field, PropertyInfo exampleClassField, ExampleClass record)
        {
            if (exampleClassField.PropertyType.Name == typeof(string).Name)
            {
                record.GetType().InvokeMember(exampleClassField.Name,
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
                    Type.DefaultBinder, record, new object[] { field });
            }
            else if (exampleClassField.PropertyType.Name == typeof(double).Name)
            {
                record.GetType().InvokeMember(exampleClassField.Name,
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
                    Type.DefaultBinder, record, new object[] { double.Parse(field) });
            }
            else if (exampleClassField.PropertyType.Name == typeof(MyOtherClass).Name)
            {
                var other = new MyOtherClass();
                // TO DO: Parse field to set properties in MyOtherClas
                record.GetType().InvokeMember(exampleClassField.Name,
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
                    Type.DefaultBinder, record, new object[] { other });
            }
        }
    }
}