1

JSON を使用して C# MVC アプリケーションをプログラミングしており、EF を使用して JSON を DB に取得しようとしています。

残念ながら、私はそのようなコードを機能させることはできません:

IEnumerable<object> NewValueSubCollection = (IEnumerable<object>)NewValue.GetType().GetProperty(col.Name).GetValue(NewValue, null);
//Where col is a property of an object of type (IEnumerable<???>)

foreach (var line in ((IEnumerable<object>)col.GetValue(originalEntity, null)).ToList<object>())
{
    Type lineType = ObjectContext.GetObjectType(line.GetType());
    var lineEntitySet = context.GetEntitySet(lineType);
    EntityKey lineKey = context.CreateEntityKey(lineEntitySet.Name, line);
    if (NewValueSubCollection.Where(lineKey).Count() == 0) //See bellow
    context.DeleteObject(line);
}

私がこれを実装した場所:

public static class LinqExtension
{
    //Enable searching in a collection is an entity Key exist... and retrieve info.
    public static IEnumerable<T> Where<T>(this IEnumerable<T> source,EntityKey key)
    {
        return Enumerable.Where(source, CreateFilterExpressionBasedOnKey<T>(key).Compile());
    }

    private static Expression<Func<TInput, bool>> CreateFilterExpressionBasedOnKey<TInput>(Type sourceType, EntityKey key)
    {
        var param = Expression.Parameter(sourceType, "");

        Expression myFilter = Expression.Constant(true);
        if (key != null)
        {
            foreach (var item in key.EntityKeyValues)
            {
                Expression Left = Expression.PropertyOrField(param, item.Key.ToString());
                Expression Right = Expression.Constant(item.Value);

                myFilter = Expression.AndAlso(myFilter, Expression.Equal(Left, Right));
            }
        }
        return Expression.Lambda<Func<TInput, bool>>(myFilter, param);
    }
}

問題は、NewValueSubCollection の型が次のようになっていることです。Where拡張機能IEnumerable<object>を通過できるようにしたいのですがIEnumerable<MyListObjectType>…。次に、実行時に例外が発生しました: System.ArgumentException: 'TOId' はタイプ 'System.Object' のメンバーではありません

私が使用する場合:

Type generic = typeof(Collection<>);
Type typeArgs = (NewValue.GetType().GetProperty(col.Name).GetValue(NewValue, null)).GetType().GetGenericArguments()[0];
Type constructed = generic.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(constructed);
o = NewValue.GetType().GetProperty(col.Name).GetValue(NewValue, null);

次のコードでコンパイル エラーが発生します。

if (o.Where(lineKey).Count() == 0) //error!!!
// 'object' does not contain a definition for 'Where' acception a first argument of type 'object' could be found (are you missing directive or an assembly reference?)
4

2 に答える 2

1

これに動的にアクセスする必要がありますが、'dynamic' キーワードを使用すると、リフレクションの頭痛の種の一部を回避できます。

したがって、この:

NewValueSubCollection.Where(lineKey).Count() == 0

これになります:

NewValueSubCollection.Cast<dynamic>().Where(d => lineKey(d)).Count() == 0

または(列挙に副作用がない場合は、より単純で効率的です)これ:

!NewValueSubCollection.Cast<dynamic>().Any(d => lineKey(d))

簡単な概念実証プログラム:

class Program
{
    static void Main(string[] args)
    {
        var list = new List<string>();
        IEnumerable<object> objects = list;
        Func<string, bool> func = s => s.Contains("x");

        list.Add("Test");
        list.Add("x");
        list.Add("mux");
        foreach (var item in objects.Cast<dynamic>().Where(d => func(d)))
            Console.WriteLine(item);
        Console.ReadKey();
    }
}
于 2012-08-01T22:54:29.630 に答える
0

最初の例でNewValueSubCollectionは、静的に型 asIEnumerable<object>であるため、パラメータ化された型Tobjectであり、式をコンパイルすると、オブジェクト クラスのプロパティを見つけようとするため、例外になります。

同様に、拡張メソッドが で定義されてo.Where(...)いるため、 は機能しません。メソッドはコンパイル時に静的に解決されます。WhereIEnumerable<>

リフレクションによってメソッドを呼び出す必要があると思いますが、Whereここでいくつかのヘルプが見つかるかもしれません:リフレクションを使用して拡張メソッドを呼び出すにはどうすればよいですか?

于 2012-08-01T21:46:23.783 に答える