Reputation: 2460
I'm trying to create a generic method that accepts a collection object, a string representation of the object's type, and a dictionary(of String,String) whose keys contain properties of interest.
I want to then generate a dynamic linq query based on these inputs. It seems though that even after converting the input collection object to a strongly-typed object, dynamic linq won't work - it says Public member 'Select' on type '{T}' not found
(where {T}
is the strong type).
Here's basically what I've got:
Sub Testing123(ByVal data As Object, ByVal fieldDefs As Dictionary(Of String, String), ByVal myObjectType as String, ByVal myCollectionType As String, ByVal myAssembly As String)
' Type of object in the collection
Dim properties = Type.GetType(myObjectType).GetProperties().Where(Function(p) fieldDefs.ContainsKey(p.Name)).ToList()
' Get type of the collection object (data)
Dim thisType = Type.GetType(String.Format("{0},{1}",myCollectionType,myAssembly))
' Create strongly-typed collection object
Dim data2 = Convert.ChangeType(data, thisType)
' Resolve select list from input
Dim selectVars As String = "new (" & String.Join(", ", fieldDefs.Keys.ToList()) & ")"
' materialise dynamic query
Dim result = data2.Select(selectVars) ' ERROR IS HERE
For Each r In result
Debug.Print(r.Title & " " & r.ViewType)
Next
End Sub
It works OK if I pass a strongly-typed collection object in (e.g. rather than ByVal data As Object
, ByVal data as MyStrongType
) and do the equivalent dynamic linq query. But it seems that making the input Object
, even though the conversion is successful (have confirmed in debug session), I get this error.
Note that the collection types are custom objects (SharePoint CSOM objects, in case that's helpful), not just List(Of T)
.
Upvotes: 0
Views: 2294
Reputation: 54417
Thinking about it further, the DLINQ version of Select
must actually require an IEnumerable
or an IQueryable
rather than an IEnumerable(Of T)
. I've had a quick look and can't find confirmation of that but I think it must be the case or it wouldn't be dynamic. In that case, you can simply cast as that type, which wouldn't require any other changes to your code.
If an IEnumerable
is all that's required then use this:
Dim result = DirectCast(data2, IEnumerable).Select(selectVars)
If an IQueryable
is required then, as your object probably doesn't implement that already, you'd need this:
Dim result = DirectCast(data2, IEnumerable).AsQueryable().Select(selectVars)
This answer is a bit of an educated guess but it seems logical, so hopefully it's accurate.
Upvotes: 2