C#反射-使用反射从分隔的字符串中填充类属性

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

我正在尝试使用从不规则CSV格式的文件中检索的数据填充类。我能够从文件中获取数据,确定文件中是否存在属性值,并从检索到的数据中创建对象。

[尝试填充类属性时,我已经尝试过:

this.GetType().GetProperty(propName).SetValue(this, newProp);

...导致异常:

System.ArgumentException:'对象类型'System.Collections.Generic.List1[System.Collections.Generic.List1 [SharpCodingTestApp.Bar]]'无法转换为类型'System.Collections.Generic.List`1 [SharpCodingTestApp.Bar]'。'

和...

this.GetType().InvokeMember(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, Type.DefaultBinder, this, new object[] { newProp });

...导致异常:

System.MissingMethodException:'方法找不到'SharpCodingTestApp.Bar'。'

这是我当前正在运行的代码:

public class FooBar
{
    private string _configFile;

    public Foo PropFoo { get; get; }
    public List<Bar> PropBar { get; set; }

    public void Load()
    {
        List<object> props = new List<object>();

        if (String.IsNullOrWhiteSpace(_configFile) != true)
        {
            //Does the config file contain all of the required settings?
            if (ConfigFileContainsRoomConfigSettings(_configFile))
            {
                //Get the information we need from the file.
                string[] configLines = GetConfigLines(_configFile);

                foreach (var line in configLines)
                {
                    var propName = line.Split(", ")[0].Trim(' ');
                    var newProp = CreatePropertyObejct(propName, line);
                    this.GetType().InvokeMember(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, Type.DefaultBinder, this, new object[] { newProp });
                }
            }
        }
    }

    private object CreatePropertyObejct(string paramPropertyName, string paramPropertyConfigString)
    {
        var prop = this.GetType().GetProperty(paramPropertyName);
        if (prop.PropertyType.Name.ToLower().Contains("list") == true)
        {
            var listType = typeof(List<>);
            var constructedListType = listType.MakeGenericType(prop.PropertyType);
            return Activator.CreateInstance(constructedListType);
        }
        else
        {
            return Activator.CreateInstance(prop.PropertyType, paramPropertyConfigString, ',');
        }
    }
}

这是文件中数据的示例:

Foo, FooVal1, FooVal2
Bar, BarVal1, BarVal2, BarVal3, BarVal4
Bar, BarVal1, BarVal2, BarVal3, BarVal4

每个定界字符串中的第一个值包含数据所属的属性名称。Bar在文件中具有多个条目,以表示列表中的每个对象。

我该如何解决异常,是否有更好的方法去做我想做的事情?

谢谢。

c# generics casting system.reflection
1个回答
0
投票

如果您正在编写反射代码,请不要使用字符串比较。并尝试预先构建和缓存所需的一切。但是,如果您不知道要问什么问题,很难找到正确的方法。

您的第一个错误正在发生,因为prop.PropertyType已经是List<T>,因此typeof(List<>).MakeGenericType(prop.PropertyType)正在定义List<List<T>>

输入数据实际上是CSV吗?数据可以包含引号,逗号和换行符吗?然后,.Split(", ")不会被剪切。您需要找到/实现适当的c#解析器。

我不清楚您打算如何处理其他所有csv列?

© www.soinside.com 2019 - 2024. All rights reserved.