Call function in dynamic linq

c# dynamic-linq linq linq-to-objects

Question

I'm attempting to use a dynamic linq select statement to invoke a function, but I keep receiving this error:

No property or field 'A' exists in type 'Tuple2'

Sample of a code

void Main()
{
    var a = new Tuple<int, int>(1,1);
    var b = new[]{ a };
    var q = b.AsQueryable().Select("A.Test(it.Item1)");

    q.Dump();
}

public static class A
{
    public static int Test(int i)
    {
        return i++;
    }
}

How should my code be modified to make this work?

When I invoke an inside functionConvert.ToInt32 For instance, it performs well.

var q = b.AsQueryable().Select("Convert.ToInt32(it.Item1)");

Additionally, using dynamic linq, how can I cast a property?

var q = b.AsQueryable().Select("((float)it.Item1)");
1
6
8/19/2013 1:08:52 PM

Accepted Answer

In my opinion, thedynamic-linq not "strong enough" to carry out such actions. It only searches for methods in the provided objects and a few unique classes:Math , Convert the different basic kinds (int , float , string , ...),Guid , Timespan , DateTime

If you run the file using ilspy/reflector, you may see a list of these kinds in plain sight. They're thereSystem.Linq.Dynamic.ExpressionParser.predefinedTypes .

I might perhaps be mistaken, but this works:.Select("Guid.NewGuid().ToString()").Cast<string>().ToArray()

demonstrating that the likelihood that this is the "right" list is fairly high.

If you're interested, there is an article here on how to change Dynamic LINQ.

Now, a wise guy would just extend that array using the dynamic linq source... However, intellectual guys aren't many here. The only people who desire blood, Blood, and particularly innards are programmers.

var type = typeof(DynamicQueryable).Assembly.GetType("System.Linq.Dynamic.ExpressionParser");

FieldInfo field = type.GetField("predefinedTypes", BindingFlags.Static | BindingFlags.NonPublic);

Type[] predefinedTypes = (Type[])field.GetValue(null);

Array.Resize(ref predefinedTypes, predefinedTypes.Length + 1);
predefinedTypes[predefinedTypes.Length - 1] = typeof(A); // Your type

field.SetValue(null, predefinedTypes);

Because the methods and properties of these types are cached after the first call to Dynamic Linq, do this (with the types you wish) BEFORE the first call to Dynamic Linq.

To add our object(s) to this "special list," we employ reflection.

12
8/19/2013 1:02:50 PM

Popular Answer

I am aware that there is a previously approved solution to this, but it did not work for me. Dynamic Linq 1.1.4 is what I'm using. I was going to run a similar query.

$.GetNewestRisk() == null

where the object denoted by $ has a public function called GetNewestRisk(). The message "Error performing query, Methods on type "Patient" are not available (at index 2)" kept appearing to me.

I discovered that the GlobalConfig object in the source code enables a custom provider to be provided, holding all of the kinds you could need to deal with. The custom provider's source code is available here:

public class CustomTypeProvider: IDynamicLinkCustomTypeProvider
{
    public HashSet<Type> GetCustomTypes()
    {
        HashSet<Type> types = new HashSet<Type>();
        types.Add(typeof(Patient));
        types.Add(typeof(RiskFactorResult));
        types.Add(typeof(PatientLabResult));
        types.Add(typeof(PatientVital));
        return types;
    }
}

I'm using it as follows:

System.Linq.Dynamic.GlobalConfig.CustomTypeProvider = new CustomType();

I may now call methods on the objects included in the expression after making this call.



Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow