这是我的代码,它通过T
字符串生成property
对象的属性。
// returning property as lambda from string
public static Func<T, object> GetPropertyFunc<T>(string property)
{
try
{
var parameter = Expression.Parameter(typeof(T), "obj");
Expression body = parameter;
foreach (var member in property.Split('.'))
{
body = Expression.PropertyOrField(body, member);
}
// conversion from Toutput to object
Expression converted = Expression.Convert(body, typeof(object));
return Expression.Lambda<Func<T, object>>(converted, parameter).Compile();
//return (Func<T, object>)Expression.Lambda(body, parameter).Compile();
}
catch (Exception ex)
{
throw ex;
}
}
接下来,我在这里使用它:
var orderParamFunc = PagedListHelper.GetPropertyFunc<T>(pagedListModel.OrderParameter.ParameterName);
IOrderedEnumerable<T> finalQuery = pagedListModel.OrderParameter.OrderAscending ? whereQuery.OrderBy(orderParamFunc) : whereQuery.OrderByDescending(orderParamFunc);
当属性不为null时,它工作正常。 我的例子有问题:
property = "Customers.Dicts.DictValue"
Customers
属性中的可以为Customers.Dicts
属性为空。
我应该在GetPropertyFunc
方法中添加什么来检查null?我不知道在何处以及如何处理条件!= null
或.HasValue
。
答案 0 :(得分:1)
如本文所述:
How to detect IsNull / NotNull when building dynamic LINQ expressions?
我建议更改foreach循环以检查构造为值类型的表达式的默认值(null)。
以下是对值类型的构造默认值的一点帮助:
Programmatic equivalent of default(Type)
以下是单元测试:
using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq.Expressions;
namespace TestProject1
{
[TestClass]
public class UnitTest1
{
class TestRefType2
{
public TestRefType2()
{
}
}
class TestRefType1
{
public TestRefType1()
{
}
public Guid VALUETYPE { get; set; }
public TestRefType2 REFTYPE { get; set; }
}
class MainType
{
public MainType()
{
}
public TestRefType1 REFTYPE { get; set; }
}
public static object GetDefault(Type type)
{
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
// returning property as lambda from string
public static Func<T, object> GetPropertyFunc<T>(string property)
{
try
{
var parameter = Expression.Parameter(typeof(T), "obj");
Expression body = parameter;
foreach (var member in property.Split('.'))
{
var prop = Expression.PropertyOrField(body, member);
body = Expression.Condition(Expression.Equal(body, Expression.Default(body.Type)), Expression.Default(prop.Type), prop);
}
// conversion from Toutput to object
Expression converted = Expression.Convert(body, typeof(object));
return Expression.Lambda<Func<T, object>>(converted, parameter).Compile();
//return (Func<T, object>)Expression.Lambda(body, parameter).Compile();
}
catch (Exception ex)
{
throw ex;
}
}
[TestMethod]
public void TestMethod1()
{
MainType t = new MainType();
t.REFTYPE = new TestRefType1();
Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.VALUETYPE");
object val = ex(t);
Assert.AreEqual(default(Guid), val);
}
[TestMethod]
public void TestMethod2()
{
MainType t = new MainType();
Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.VALUETYPE");
object val = ex(t);
Assert.AreEqual(default(Guid), val);
}
[TestMethod]
public void TestMethod3()
{
MainType t = new MainType();
t.REFTYPE = new TestRefType1();
var guid = Guid.NewGuid();
t.REFTYPE.VALUETYPE = guid;
Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.VALUETYPE");
object val = ex(t);
Assert.AreEqual(guid, val);
}
[TestMethod]
public void TestMethod4()
{
MainType t = new MainType();
t.REFTYPE = new TestRefType1();
Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE");
object val = ex(t);
Assert.AreNotEqual(default(TestRefType1), val);
}
[TestMethod]
public void TestMethod5()
{
MainType t = new MainType();
t.REFTYPE = new TestRefType1();
Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.REFTYPE");
object val = ex(t);
Assert.AreEqual(default(TestRefType2), val);
}
[TestMethod]
public void TestMethod6()
{
MainType t = new MainType();
Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.REFTYPE");
object val = ex(t);
Assert.AreEqual(default(TestRefType2), val);
}
[TestMethod]
public void TestMethod7()
{
MainType t = new MainType();
t.REFTYPE = new TestRefType1();
var reftype2 = new TestRefType2();
t.REFTYPE.REFTYPE = reftype2;
Func<MainType, object> ex = GetPropertyFunc<MainType>("REFTYPE.REFTYPE");
object val = ex(t);
Assert.AreEqual(reftype2, val);
}
}
}
答案 1 :(得分:0)
在调用GetPropertyFunc
方法之前,您需要检查这些属性的空值。这样,GetPropertyFunc
方法将返回一个lambda,其中不包含那些属性。
老实说,我不确定你要做什么,除了你试图创建一个你最终会在某个地方使用的查询。如果我们知道你的目标和意图,也许有更好的方法来实现你想要的东西。