例如,我有一些带有一些属性的类:
public class SomeClass
{
public Version Version { get; set; }
}
我有一个包含样本数据的此类型列表:
var list = new List<SomeClass>();
for (var i = 0; i < 1000; i++)
{
list.Add(new SomeClass
{
Version = new Version(i, i / 2, i / 3, i / 4),
});
}
我想编写使用Version.Equals方法按版本过滤的方法:
var filterValue = new Version(12, 6, 4, 3);
var modelType = typeof(SomeClass);
var propertyType = typeof(Version);
var arg = Expression.Parameter(modelType, "x");
var property = Expression.Property(arg, "Version");
var value = Expression.Convert(Expression.Constant(filterValue), propertyType);
var versionEqualsMethod = typeof(Version).GetMethod("Equals", new[] { typeof(Version) });
/////////
Expression inst = null; // <-- ???
/////////
var expr = Expression.Call(inst, versionEqualsMethod, property, value);
var delegateType = typeof(Func<,>).MakeGenericType(modelType, typeof(bool));
var delegateValue = Expression.Lambda(delegateType, expr, arg).Compile();
var genericMethod =
typeof(Enumerable).GetMethods()
.First(
method =>
method.Name == "Where" && method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 1 && method.GetParameters().Length == 2)
.MakeGenericMethod(modelType);
var result = genericMethod.Invoke(null, new object[] { list, delegateValue });
我在Expression.Call中使用什么作为实例?
更新
解决方案是:
var expr = Expression.Call(property, versionEqualsMethod, value);
答案 0 :(得分:4)
你通常会这样做:
var filterValue = new Version(12, 6, 4, 3);
var modelType = typeof(SomeClass);
var propertyType = typeof(Version);
var arg = Expression.Parameter(modelType, "x");
var property = Expression.Property(arg, "Version");
// Changes from here onward
var value = Expression.Constant(filterValue);
var versionEqualsMethod = typeof(Version).GetMethod("Equals", new[] { typeof(Version) });
var expr = Expression.Call(property, versionEqualsMethod, value);
因为Equals
将被用作:
model.Version.Equals(filterValue);
我不处理model.Version == null
案件!
请注意,您不需要Expression.Convert
。
如果&#34;包含方法&#34;你正在做的事情是好的。 (你将此代码放在这里的方法)是非泛型的,但通常它是一个通用方法,它具有通用参数modelType
,所以代码的最后部分会有所不同(从var delegateType =
开始),因为您可以直接使用TModelType
泛型类型。
答案 1 :(得分:0)
也许我错过了某些东西,但这不会起作用:
var results = list.Where(sc => sc.Version == filterVersion);
答案 2 :(得分:0)
你想要完成的事情更容易用反射做。检查this running online example。 (如果我理解正确的话......如果你能提供你想写的功能的签名,那会很有帮助。)
<强>实施强>
public static class Extensions
{
public static IEnumerable<T> Filter<T>(
this IEnumerable<T> enumerable, string propertyName, object filterValue)
{
var elementType = typeof (T);
var property = elementType.GetProperty(propertyName);
return enumerable.Where(element =>
{
var propertyValue = property.GetMethod.Invoke(element, new object[] {});
return propertyValue.Equals(filterValue);
});
}
}
<强>用法强>
var list = new List<SomeClass>();
for (var i = 0; i < 1000; i++)
{
list.Add(new SomeClass {Version = new Version(i, i/2, i/3, i/4)});
}
var filteredList = list.Filter("Version", new Version(12, 6, 4, 3));
Console.WriteLine(filteredList.Single().Version);