Как вызвать функцию FirstOrDefault(customPredicate) с помощью ReflectionC#

Место общения программистов C#
Ответить
Anonymous
 Как вызвать функцию FirstOrDefault(customPredicate) с помощью Reflection

Сообщение Anonymous »

Я исследовал эту тему, но мне кажется, это сложная тема. Я использую отражение, чтобы иметь возможность динамически вызывать метод «FirstOrDefault» из моего _dbContext.Table
Это строка, которую мне нужно сделать динамической:

Код: Выделить всё

var tableObject = _dbContext.Table.FirstOrDefault(x => x.Id == 332)
Это фрагмент кода моего решения:

Код: Выделить всё

    var contextType = _dbContext.GetType();
var contextTableReference = contextType.GetProperties().FirstOrDefault(x => x.Name.Contains(tableName));
var tableInstance = GetInstanceOfTable(tableName);
var tableType = tableInstance.GetType();
var contextTableMethod = typeof(Queryable).GetMethods().FirstOrDefault(x => x.Name.Contains("FirstOrDefault"));
var DbSetOfT = contextTableReference.GetValue(_dbContext);

var col = "PersonId";
var val = 332;

ParameterExpression parameter = Expression.Parameter(tableType, "x");

MemberExpression property = Expression.Property(parameter, col);
ConstantExpression rightSide = Expression.Constant(val);
BinaryExpression operation = Expression.Equal(property, rightSide);
Type delegateType = typeof (Func).MakeGenericType(tableType, typeof (bool));
LambdaExpression predicate  = Expression.Lambda(delegateType, operation, parameter);

//Contains the reference to the First or Default method from the Queryable class

MethodInfo genericMethod = contextTableMethod.MakeGenericMethod(new[] { tableType});

object retVal = genericMethod.Invoke(null, new object[] {DbSetOfT, predicate});
Вот моя вспомогательная функция для создания экземпляра объекта заданного типа

Код: Выделить всё

    private readonly string FullyQualifiedAssemblyName = "DBManager.Models.@, DBManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";

internal object GetInstanceOfTable(string tableName)
{
Type t = Type.GetType(GetFullAssemblyNameForTable(tableName));

return Activator.CreateInstance(t);
}

internal string GetFullAssemblyNameForTable(string tableName)
{
return FullyQualifiedAssemblyName.Replace("@", tableName);
}
Моя проблема заключается в том, что я пытаюсь вызвать метод:

Код: Выделить всё

    object retVal = genericMethod.Invoke(null, new object[] {DbSetOfT , predicate});
Выдает ошибку:

System.ArgumentException: объект типа «DBManager.Models.Table» невозможно преобразовать в тип «System.Linq.IQueryable`1[DBManager.Models.Table]».

Я думаю, что, возможно, я вызываю метод с неверными параметрами.
Вот сообщение, которое я нашел во время исследования:
Как вызвать IDBSet.FirstOrDefault(predicate) с помощью отражения?
ОБНОВЛЕНИЕ
Я реализовал решение, предложенное Дэвидом, и очистил некоторый ненужный код:

Код: Выделить всё

     var DbSetOfT = contextTableReference.GetValue(_dbContext);
object retVal = genericMethod.Invoke(null, new object[] {DbSetOfT, predicate});
и я получаю новую ошибку

System.ArgumentException: объект типа 'System.Linq.Expressions.Expression1

Код: Выделить всё

1[System.Func
2[DBManager.Models.Table,System.Boolean]]' невозможно преобразовать в тип 'DBManager.Models.Table'.


Подробнее здесь: https://stackoverflow.com/questions/732 ... reflection
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»