В моем текущем проекте в репозитории используется EntityFramework со многими таблицами как News. Итак, каждый раз у нас есть новый входной функционал, мы создаем соответствующую базу данных, генерируем edmx, создаем новый метод в репозитории. Пример: db.News.Where (c => c.Name == 'myNews'); db.Arts.Where (c => c.ArticleName == 'myArticle');Динамический параметр выражения лямбда
Я ищу способ избежать записи каждый раз, когда код действительно похож.
Я создал этот код с помощью Generic. Так что это образец кода, идеал в порядке, я могу создать стандартный метод, сначала взяв propertyName и строковый поиск. Оно работает.
Декларация
public class SampleClass
{
public string SomeField = "Test";
}
public class ConfSampleClass2
{
public Type Type { get; set; }
}
Вызов:
IQueryable result = GetCompaniesA<SampleClass2>("Name", "alpine");
Метод:
public IQueryable GetCompaniesA<T>(string propertyName, string search)
{
try
{
IQueryable<T> results = null;
SampleClass2 sc2 = new SampleClass2();
List<SampleClass2> listSc2 = new List<SampleClass2>();
listSc2.Add(new SampleClass2() { Name = "alpine" });
listSc2.Add(new SampleClass2() { Name = "Statue" });
listSc2.Add(new SampleClass2() { Name = "Gateau" });
//listSc2.Where(c => c.Name == "alpine");
IQueryable<SampleClass2> queryableData = listSc2.AsQueryable<SampleClass2>();
// Compose the expression tree that represents the parameter to the predicate.
ParameterExpression pe = Expression.Parameter(typeof(T),typeof(T).Name);
Expression member = Expression.Property(pe, typeof(T).GetProperty(propertyName));
Expression left = Expression.Call(member, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
Expression right = Expression.Constant(search);
Expression e1 = Expression.Equal(left, right);
MethodCallExpression whereCallExpression =
Expression.Call(
typeof(Queryable),
"Where",
new Type[] { queryableData.ElementType },
queryableData.Expression,
Expression.Lambda<Func<T, bool>>(e1, new ParameterExpression[] { pe }));
return queryableData.Provider.CreateQuery(whereCallExpression);
}
catch (Exception ex)
{
throw ex;
}
}
Но я хотел бы пойти дальше избегать использования общего, но с использованием динамического, чтобы избежать название связи. Так что я изменить метод, чтобы получить этот один:
Вызов:
Console.WriteLine(GetCompaniesDynamic(new ConfSampleClass2(){ Type=typeof(SampleClass2) },"Name", "alpine"));
Метод:
public IQueryable GetCompaniesDynamic(dynamic dynamicObj, string propertyName, string search)
{
try
{
IQueryable results = null;
SampleClass2 sc2 = new SampleClass2();
List<SampleClass2> listSc2 = new List<SampleClass2>();
listSc2.Add(new SampleClass2() { Name = "alpine" });
listSc2.Add(new SampleClass2() { Name = "Statue" });
listSc2.Add(new SampleClass2() { Name = "Gateau" });
IQueryable<SampleClass2> queryableData = listSc2.AsQueryable<SampleClass2>();
ParameterExpression pe = Expression.Parameter(dynamicObj.Type, dynamicObj.Type.Name);
Expression member = Expression.Property(pe, dynamicObj.Type.GetProperty(propertyName));
Expression left = Expression.Call(member, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
Expression right = Expression.Constant(search);
Expression e1 = Expression.Equal(left, right);
//the issue appears on this line ParameterExpression of type //'EntityFrameworkGeolocationExpression.SampleClass2' cannot be used for delegate parameter //of type 'System.Object', I can't compile if I replace Object by Dynamic.
MethodCallExpression whereCallExpression =
Expression.Call(
typeof(Queryable),
"Where",
new Type[] { queryableData.ElementType },
queryableData.Expression,
Expression.Lambda<Func<Object, bool>>(e1, new ParameterExpression[] { pe }));
return results = queryableData.Provider.CreateQuery(whereCallExpression);
}
catch (Exception ex)
{
throw ex;
}
}
Я пытаюсь найти способ, чтобы действительно прошел динамический объект, поэтому в в моем репозитории я заменю новости, статьи и объекты, вызванные простым запросом, выражением три. Я нахожу много темы, а с кем-то, я читал, это невозможно. Следующим шагом после этого является эволюция выражения три путем изменения параметров.
Помогите мне пойти дальше?
С наилучшими пожеланиями, Александр
Возможно, вам нужно просто скопировать код EF напрямую: 'db.News.Where (c => c.Name == 'myNews')'. Почему это не работает для вас? – usr
Спасибо за ваше предложение НО, я хотел бы разработать свой код, у меня нет только новостей и статей, у меня теперь около 30 таблиц, поэтому я ищу универсальное решение, позволяющее выполнить общий вызов. Это позволяет также абстрагироваться от дальнейшего обращения к репозиторию. – user2416437
@ user2416437 - Абстрактное выражение, чтобы вы могли использовать строки или 'dynamic' вместо фактических свойств - плохая идея.Вы теряете безопасность типа, вы теряете ошибки компиляции, когда ваш объект меняется, и вы теряете intellisense. Это плохая идея. – Bobson