繁体   English   中英

在动态对象上找不到属性或字段

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM