簡體   English   中英

C# 反射 - 使用反射從分隔字符串填充類屬性

[英]C# Reflection - Populate class properties from delimited strings using reflection

我正在嘗試使用從不規則 CSV 格式文件中檢索到的數據填充一個類。 我能夠從文件中獲取數據,確定文件中是否存在屬性值,並從檢索到的數據創建對象。

在嘗試填充類屬性時,我嘗試過:

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

...導致異常:

System.ArgumentException: 'System.Collections.Generic.List 1[System.Collections.Generic.List 1[SharpCodingTestApp.Bar]]'類型的對象無法轉換為類型'System.Collections.Generic.List`1[SharpCodingTestApp] 。酒吧]'。'

和...

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 在文件中有多個條目來表示列表中的每個對象。

我如何解決異常,是否有更好的方法來做我想做的事情?

謝謝。

如果您正在編寫反射代碼,請不要使用字符串比較。 並嘗試預先構建和緩存您需要的一切。 但是,如果您不知道要問什么問題,則很難找到正確的方法。

你的第一個錯誤發生了,因為prop.PropertyType已經是一個List<T> ,所以typeof(List<>).MakeGenericType(prop.PropertyType) ,正在定義一個List<List<T>>

輸入數據實際上是 csv 嗎? 數據可以包含引號、逗號和換行符嗎? 然后.Split(", ")不會削減它。 您需要找到/實現一個合適的 c# 解析器。

我不太清楚您要對其他每個 csv 列做什么?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM