Tôi đã cố triển khai loại nội dung này. Đã cho tôi một ngày để tìm hiểu. Giải pháp của tôi dựa trên bộ lọc trong vòng lặp dựa trên Mảng vị ngữ. Như một lưu ý, nó hoàn toàn chung và dựa trên phản ánh bởi vì thông tin duy nhất về lớp và trường là String. Để làm cho nó đơn giản, tôi gọi trực tiếp lớp Model nhưng trong một dự án bạn nên đi bởi một người điều khiển đang gọi Model.
Vì vậy, ở đây chúng tôi đi: Phần mẫu trong đó T là một Generic trong lớp
public class DALXmlRepository<T> where T : class
{
public T GetItem(Array predicate)
{
IQueryable<T> QueryList = null;
QueryList = ObjectList.AsQueryable<T>().Where((Expression<Func<T, bool>>)predicate.GetValue(0));
for (int i = 1; i < predicate.GetLength(0); i++)
{
QueryList = QueryList.Where((Expression<Func<T, bool>>)predicate.GetValue(i));
}
if (QueryList.FirstOrDefault() == null)
throw new InvalidOperationException(this.GetType().GetGenericArguments().First().Name + " not found.");
return QueryList.FirstOrDefault();
}
}
Bây giờ LambdaExpression Builder, đó là một cơ sở (với loại Chuỗi hay cái gì khác), bạn có thể cải thiện nó với hơn functionnality:
private static Expression BuildLambdaExpression(Type GenericArgument, string FieldName, string FieldValue)
{
LambdaExpression lambda = null;
Expression Criteria = null;
Random r = new Random();
ParameterExpression predParam = Expression.Parameter(GenericArgument, r.Next().ToString());
if (GenericArgument.GetProperty(FieldName).PropertyType == typeof(string))
{
Expression left = Expression.PropertyOrField(predParam, FieldName);
Expression LefttoUpper = Expression.Call(left, "ToUpper", null, null);
//Type du champ recherché
Type propType = GenericArgument.GetProperty(FieldName).PropertyType;
Expression right = Expression.Constant(FieldValue, propType);
Expression RighttoUpper = Expression.Call(right, "ToUpper", null, null);
Criteria = Expression.Equal(LefttoUpper, RighttoUpper);
}
else
{
Expression left = Expression.PropertyOrField(predParam, FieldName);
Type propType = GenericArgument.GetProperty(FieldName).PropertyType;
Expression right = Expression.Constant(Convert.ChangeType(FieldValue, propType), propType);
Criteria = Expression.Equal(left, right);
}
lambda = Expression.Lambda(Criteria, predParam);
return lambda;
}
Bây giờ chức năng gọi:
public static Hashtable GetItemWithFilter(string Entity, XMLContext contextXML, Hashtable FieldsNameToGet, Hashtable FieldFilter)
{
//Get the type
Type type = Type.GetType("JP.Model.BO." + Entity + ", JPModel");
Type CtrlCommonType = typeof(CtrlCommon<>).MakeGenericType(type);
//Making an instance DALXmlRepository<xxx> XMLInstance = new DALXmlRepository<xxx>(contextXML);
ConstructorInfo ci = CtrlCommonType.GetConstructor(new Type[] { typeof(XMLContext), typeof(String) });
IControleur DalInstance = (IControleur)ci.Invoke(new object[] { contextXML, null });
//Building the string type Expression<func<T,bool>> to init the array
Type FuncType = typeof(Func<,>).MakeGenericType(type ,typeof(bool));
Type ExpressType = typeof(Expression<>).MakeGenericType(FuncType);
Array lambda = Array.CreateInstance(ExpressType,FieldFilter.Count);
MethodInfo method = DalInstance.GetType().GetMethod("GetItem", new Type[] { lambda.GetType() });
if (method == null)
throw new InvalidOperationException("GetItem(Array) doesn't exist for " + DalInstance.GetType().GetGenericArguments().First().Name);
int j = 0;
IDictionaryEnumerator criterias = FieldFilter.GetEnumerator();
criterias.Reset();
while (criterias.MoveNext())
{
if (!String.IsNullOrEmpty(criterias.Key.ToString()))
{
lambda.SetValue(BuildLambdaExpression(type, criterias.Key.ToString(), criterias.Value.ToString()),j);
}
else
{
throw new JPException(JPException.MessageKey.CONTROLER_PARAMFIELD_EMPTY, "GetItemWithFilter", criterias.Key.ToString());
}
j++;
}
Object item = method.Invoke(DalInstance, new object[] { lambda });
}
Đối số là: Thực thể chuỗi: Tên lớp thực thể. XMLContext: nó là đơn vị công việc của kho lưu trữ, đối số tôi sử dụng để khởi tạo lớp Mô hình Trường HashtableNameToGet: Chỉ mục/giá trị của danh sách trường tôi muốn lấy lại Trường HashtableFilter: khóa/Giá trị với FieldName/Nội dung được sử dụng để tạo biểu thức Lambda
Chúc may mắn.
Tôi đã cố gắng tìm giải pháp tương tự, vì chúng tôi sử dụng công cụ ORML cũ của chúng tôi do nhóm của chúng tôi phát triển, hỗ trợ các hoạt động phụ thêm bằng "AND" hoặc "OR" và mã của chúng tôi phụ thuộc rất nhiều vào tiện ích mở rộng đó. Cho đến nay chúng tôi không thể chuyển sang LINQ, nhưng về cơ bản linq tạo IExpression và nếu bạn tìm cách tạo ra cây IExpression của chính mình, điều đó có thể hữu ích. –