Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在动态对象上找不到属性或字段_C#_Linq - Fatal编程技术网

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

C# 在动态对象上找不到属性或字段,c#,linq,C#,Linq,我曾经做过一些数据库查询,到目前为止,它工作得非常好。我可以将字符串传递给Select以选择如下字段: var output = myDatabaseTable.Select("Foo, Bar"); 比如说。当您传递一个字符串变量而不是硬编码的字符串时,这种能力显然是有效的。我现在遇到的问题是,库使用IEnumerable而不是IEnumerable,因为很明显,它在运行时之前无法知道t。我使用它来选择数据并最终将其返回给客户机,它可以很好地输出原始数据,但现在我希望能够在返回数据之前进行更

我曾经做过一些数据库查询,到目前为止,它工作得非常好。我可以将字符串传递给Select以选择如下字段:

var output = myDatabaseTable.Select("Foo, Bar");
比如说。当您传递一个字符串变量而不是硬编码的字符串时,这种能力显然是有效的。我现在遇到的问题是,库使用IEnumerable而不是IEnumerable,因为很明显,它在运行时之前无法知道t。我使用它来选择数据并最终将其返回给客户机,它可以很好地输出原始数据,但现在我希望能够在返回数据之前进行更多的处理,这需要首先在数据库上运行查询。我可以这样做:

var materializedResults = output.Cast<dynamic>().ToList();
var foos = materializedResults.Select("Foo");
现在,我得到一个System.Linq.Dynamic.ParseException,消息为“Object”类型中不存在字段“Foo”的属性注意:我可以在调试器中看到,materializedResults实际上具有所有预期属性

因此,在强制转换到一个列表以便我可以潜在地遍历它并修改一些值之后,我就不能再查询它了

所以我的问题是,我如何使用select、groupby、orderby等作为字符串提供的动态查询,具体化结果,然后实际动态处理这些结果

我想如果我可以转换为实际类型而不是动态类型,它可能会起作用,因此我尝试了以下方法:

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,这样我就可以从第一项获取类型,然后再获取该类型。

如果执行stuff.Cast.ToList,您将收到IEnumerable,并且type对象上没有属性Foo

你可能会问的问题是,你怎么能得到IList?!您可以这样做:

// 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;
    }

您的强制转换为默认值,将导致错误

(output as System.Collections.Generics.IEnumerable)
此强制转换指定了正确的接口,请重试

(output as System.Collections.IEnumerable).Cast<dynamic>().ToList()

这与您的问题有点相切,但您在这里实现了什么,而不是使用普通的旧数据表实现的呢?通过这种方式,LINQ从C到某些查询提供程序的强类型翻译的全部好处都被完全消除了,如果你不得不像这样加入反射的话,这一点就更加明显了。@Jeroenmoster:这是一个公平的观点,但我现在已经非常了解它了。我认为手工构造复杂的SQL语句稍微容易一些,而且这些挑战也难以克服。我将多个表/视图/表值函数/存储过程连接到一个数据mashup中。除此之外,我现在想让它在原则上工作@JeroenMostert:我还要补充一点,您仍然可以获得LINQ的一些好处,比如我现在需要撤销的延迟执行!我担心事情会是这样的继续-我将继续使用手工编写的复杂SQL和LINQ对象,这仍然很好。谢谢。这比我的解决方案要干净得多。你只是发布了相同的答案,然后删除了它。我很感激你的热情,但这仍然是错误的。我已经铸造到IEnumerable,我没有铸造问题。它没有给我错误,只是没有给我所需要的。
(output as System.Collections.IEnumerable).Cast<dynamic>().ToList()