[英]Can't find property or field on a dynamic object
我使用Dynamic Linq进行一些数据库查询,到目前为止,它的运行情况确实很好。 我可以将字符串传递给Select
以选择字段,如下所示:
var output = myDatabaseTable.Select("Foo, Bar");
例如。 显然,当您传递字符串变量而不是硬编码的字符串时,功能很强大。 我现在遇到的问题是使用IEnumerable
而不是IEnumerable<T>
的库,因为,显然,它直到运行时才知道T
我正在使用它来选择数据并最终将其返回给客户端,并且可以很好地处理原始数据,但是现在我希望能够在返回数据之前进行更多处理,这需要使查询继续运行首先是数据库。 我可以做这样的事情:
var materializedResults = output.Cast<dynamic>().ToList();
这将使查询运行。 但是问题是,一旦我做完了,看来我再也不能使用动态linq了。 例如,如果我做了这样的事情:
var foos = materializedResults.Select("Foo");
现在,我得到一个System.Linq.Dynamic.ParseException
,消息No property of field 'Foo' exists in type 'Object'
(注意:我可以在调试器中看到, materializedResults
实际上具有所有预期的属性)。
因此,在强制转换为List
,我可能会遍历该List
并修改某些值,因此无法再查询它。
所以我的问题是,如何进行动态查询(以字符串形式提供select,group by,order by等),具体化结果,然后实际地动态处理这些结果?
我想也许我可以将其转换为实际类型而不是dynamic
类型,所以我尝试了一下:
var d = output.Cast<dynamic>().ToList();
MethodInfo method = typeof(Enumerable).GetMethod("Cast", new[] {typeof(IEnumerable)});
method = method.MakeGenericMethod(d.First().GetType());
output = method.Invoke(d, new[] {d}) as IEnumerable;
这很丑,需要我投两次。 第一次dynamic
因此我可以从第一个项目中获取类型,然后再次获取该类型。
如果执行YourStuff.Cast<dynamic>.ToList()
,将收到IEnumerable<object>
,并且类型object
上没有属性Foo
。
您可能会问的问题,如何获得IList<TheActualType>
? 您可以这样操作:
// for IEnumerable
public static IList ToAnonymousList(this IEnumerable enumerable)
{
var enumerator = enumerable.GetEnumerator();
if (!enumerator.MoveNext())
throw new Exception("?? No elements??");
var value = enumerator.Current;
var returnList = (IList) typeof (List<>)
.MakeGenericType(value.GetType())
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
returnList.Add(value);
while (enumerator.MoveNext())
returnList.Add(enumerator.Current);
return returnList;
}
// for IQueryable
public static IList ToAnonymousList(this IQueryable source)
{
if (source == null) throw new ArgumentNullException("source");
var returnList = (IList) typeof (List<>)
.MakeGenericType(source.ElementType)
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
foreach (var elem in source)
returnList.Add(elem);
return returnList;
}
这是一个简单的扩展方法,以后可以使用,例如:
var test = (new[]
{
new
{
Property1 = "10",
Property2 = "10",
Property3 = 1
}
}
.Select("New(Property1, Property2)"))
.ToAnonymousList();
您的演员表默认设置为会导致错误
(output as System.Collections.Generics.IEnumerable)
此演员指定了正确的接口,然后重试
(output as System.Collections.IEnumerable).Cast<dynamic>().ToList()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.