2

リフレクションを使用して作成されたオブジェクトのリストがあります。それらはすべて同じ型ですが、コンパイル時には型が不明です。

このリストを(リフレクションも使用して)任意のIEnumerableであるオブジェクト プロパティに割り当てる最良の方法を見つけようとしています。

List<object>
ArrayList
Custom : List<object>

私が持っている唯一のアプローチは、プロパティが ICollection であると想定し、IEnumerable をループして各項目を追加することです。(以下を参照してください。listは IEnumerable ソース、keyはオブジェクト プロパティの文字列名、 はresultオブジェクト自体です)

foreach (object item in list) {
    PropertyInfo prop = result.GetType().GetProperty(key);
    var collection = prop.GetValue(result, null);

    Type collectionType = collection.GetType();
    MethodInfo add = collectionType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance);

    add.Invoke(collection, new object[] { item });
}
4

2 に答える 2

0

タイプが不明な既存のコレクションに項目を追加するには、いくつかの方法があります。

IListインターフェイスをチェックするか、Addフォールバックとしてメソッドをチェックします。

public void Add(object obj, string propertyName, IEnumerable enumerable)
{
    Action<object> add;

    PropertyInfo prop = obj.GetType().GetProperty(propertyName);
    var property = prop.GetValue(obj, null);

    var collection = property as IList;

    // Check for IList
    if(collection != null)
    {
        add = item => collection.Add(item);
    }
    // Try to get an Add method as fallback
    else
    {
        var objType = obj.GetType();
        var addMethod = objType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance);

        // Property doesn't support Adding
        if(addMethod == null) throw new InvalidOperationException("Method Add does not exist on class " + objType.Name);

        add = item => addMethod.Invoke(obj, new object[] { item });
    }

    foreach (var item in enumerable)
    {
        add(item);
    }
}

よりタイプセーフであるため、おそらくMarcの方法を使用します。

public class Foo
{
    public Foo()
    {
        Bar = new List<string>();
    }

    public List<string> Bar { get; set; }
    public string Qux { get; set; }
}

var result = new Foo();
var key = "Bar";

var list = new List<object> { "A", "B" };

Add(result, key, list);
于 2013-08-15T11:43:24.913 に答える