簡體   English   中英

使用C#中的反射添加到未知類型的集合

[英]Add to a collection of unknown type using reflection in c#

因此,我正在使用反射來遍歷一個對象的屬性,並使用相同名稱的屬性填充另一個對象上的值。 這很好用,但是當屬性類型是一個集合時,問題就來了。 我希望能夠遍歷源集合中的每個對象,並用源集合中的對象填充相同的列表。

public class SourceMessage
{
    public string Name { get; set; }
    public int Version { get; set; }
    public IList<ValueDefinition> Values { get; set; }
}

public class ValueDefinition
{
    public string Name { get; set; }
    public string Value { get; set; }
}

public class TargetObject
{
    public TargetObject()
    {
        Values = new List<TargetValueDefinition>();
    }
    public string Name { get; set; }
    public int Version { get; set; }
    public IList<TargetValueDefinition> Values { get; set; }
}

public class TargetValueDefinition
{
    public string Name { get; set; }
    public string Value { get; set; }
}

然后,我使用反射從源中填充目標。

public static void PopulateFromMessage<T, TS>(ref T targetEntity, TS message)
{
    var sourceType = typeof(TS);
    var targetType = typeof(T);

    foreach (var targetPropInfo in targetType.GetProperties())
    {
        if (sourceType.GetProperty(targetPropInfo.Name) != null)
        {
            var obj = sourceType.GetProperty(targetPropInfo.Name);
            if (obj.PropertyType.Namespace == "System.Collections.Generic")
            {
                //var x = targetType.GetProperty(targetPropInfo.Name);
                //PopulateFromMessage(ref x, sourceType.GetProperty(targetPropInfo.Name));
                continue;
            }
            targetPropInfo.SetValue(targetEntity, sourceType.GetProperty(targetPropInfo.Name).GetValue(message), null);
        }
    }
}

因此,調用此方法將是這樣的:

private void DenormalizeMessage(SourceMessage message)
{
    var newTargetObject = new TargetObject();
    PopulateFromMessage(ref newTargetObject , message);
}

我可以確定該屬性何時是一個集合,但不確定如何創建新的TargetValueDefinitions以及如何使用ValueDefinitions中的值填充它們。 最后,它幾乎是TargetObject形式的SourceMessage的副本。

這一切都源於接收消息並將它們轉換為具有相同屬性名稱的對象。

您應該為每個類創建一個接口(在接口上實現方法和屬性),並在每個類中實現它。 之后,在函數PopulateFromMessage中應指定方法所允許的接口,這樣您就可以直接使用具有T和TS泛型類型的類的屬性。

免責聲明:這樣做是非常不安全的,並且會做出很多假設,但它應該使您走上正確的道路。

將您的方法更改為此:

public static void PopulateFromMessage<T, TS>(T targetEntity, TS message)
    {
        var sourceType = typeof (TS);
        var targetType = typeof (T);

        foreach (var targetPropInfo in targetType.GetProperties())
        {
            if (targetPropInfo.PropertyType.IsGenericType)
            {
                if (targetPropInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>))
                {
                    var originalList = sourceType.GetProperty(targetPropInfo.Name).GetValue(message) as IList;

                    if (originalList != null)
                    {
                        var argumentType = targetPropInfo.PropertyType.GetGenericArguments();
                        var listType = typeof (List<>);
                        var concreteType = listType.MakeGenericType(argumentType);
                        var newList = Activator.CreateInstance(concreteType) as IList;

                        foreach (var original in originalList)
                        {
                            var targetValue = Activator.CreateInstance(argumentType[0]);

                            // do this yourself. Here we're converting ValueDefinition to TargetValueDefinition
                            // targetValue.Fill(original);
                        }

                        targetPropInfo.SetValue(targetEntity, newList);
                    }
                }
            }
            else
            {
                if (sourceType.GetProperty(targetPropInfo.Name) != null)
                {
                    var obj = sourceType.GetProperty(targetPropInfo.Name);
                    if (obj.PropertyType.Namespace == "System.Collections.Generic")
                    {
                        //var x = targetType.GetProperty(targetPropInfo.Name);
                        //PopulateFromMessage(ref x, sourceType.GetProperty(targetPropInfo.Name));
                        continue;
                    }
                    targetPropInfo.SetValue(targetEntity, sourceType.GetProperty(targetPropInfo.Name).GetValue(message), null);
                }
            }
        }
    }

如果您的問題是遍歷單個屬性(當它是一個集合時)中包含的項目,那么關鍵是將屬性值讀入動態變量而不是默認情況下的對象變量,這樣您就可以將foreach用於它。

dynamic propVal = inputProperty.GetValue(item);
foreach (var subItem in propVal)
{    
//do your stuff
}

暫無
暫無

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

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