Call function in dynamic linq - c#

I'm trying to call a function in a dynamic linq select statement, but im getting error:
No property or field 'A' exists in type 'Tuple2'
Example 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 I change my code to get this working?
If I call built in function Convert.ToInt32 for example it works fine.
var q = b.AsQueryable().Select("Convert.ToInt32(it.Item1)");
Also how do I cast a property using dynamic linq?
var q = b.AsQueryable().Select("((float)it.Item1)");

I'll say that the dynamic-linq isn't "strong enough" to do these things. It looks for methods only in the given objects and some special classes: Math, Convert, the various base types (int, float, string, ...), Guid, Timespan, DateTime
The list of these types is clearly visible if you use ilspy/reflector on the file. They are in System.Linq.Dynamic.ExpressionParser.predefinedTypes .
Now, clearly I could be wrong, but this works: .Select("Guid.NewGuid().ToString()").Cast<string>().ToArray()
showing that it's quite probable that that is the "correct" list.
There is an article here on how to modify Dynamic LINQ if you are interested http://www.krizzcode.com/2012/01/extending-dynamiclinq-language.html
Now, an intelligent man would take the source of dynamic linq and simply expand that array... But here there aren't intelligent men... There are only programmers that want blood! Blood but especially innards!
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);
Do this (with the types you want) BEFORE the first call to Dynamic Linq (because after the first call the methods/properties of these types are cached)
Explanation: we use reflection to add our object(s) to this "special list".

I know there is already an accepted answer on this but it did not work for me. I am using Dynamic Linq 1.1.4. I wanted to do a query like this
$.GetNewestRisk() == null
Where GetNewestRisk() is a public method on the object represented by $. I kept getting this error "Error running query, Methods on type 'Patient' are not accessible (at index 2)".
I found in the source code there is a GlobalConfig object that allows a custom provider to be assigned which will hold all of the types you may want to work with. Here is the source code for the custom provider:
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;
}
}
Here is how I am using it:
System.Linq.Dynamic.GlobalConfig.CustomTypeProvider = new CustomType();
After making this call I am able to call methods on the objects inside of the expression.

#xanatos answer doesn't work for .Net Core version. So I've found something similar related by #Kent on the System.Dynamic.Linq.Core tests DynamicExpressionParserTests written by the library's author himself.
The given TestCustomTypeProviderClass allows you to use the DynamicLinqType class annotation which is pretty usefull for this problem.
To answer to question, you then just needed to defined the class (ensure to annotate with DynamicLinqType) :
[DynamicLinqType]
public static class A
{
public static int Test(int i)
{
return i++;
}
}
Add a customTypeProvider as mentioned above :
private class TestCustomTypeProvider : AbstractDynamicLinqCustomTypeProvider, IDynamicLinkCustomTypeProvider
{
private HashSet<Type> _customTypes;
public virtual HashSet<Type> GetCustomTypes()
{
if (_customTypes != null)
{
return _customTypes;
}
_customTypes = new HashSet<Type>(FindTypesMarkedWithDynamicLinqTypeAttribute(new[] { GetType().GetTypeInfo().Assembly }));
return _customTypes;
}
}
and use a ParsingConfig with the configurable Select to call it :
var config = new ParsingConfig
{
CustomTypeProvider = new TestCustomTypeProvider()
};
var q = b.AsQueryable().Select(config, "A.Test(it.Item1)");

#Armand has put together a brilliant solution for this issue, and being the only solution I was able to find regarding this I want to add to it for anyone who tries the same approach.
The class that is marked with...
[DynamicLinqType]
... must be taken into consideration when you run the following line:
FindTypesMarkedWithDynamicLinqTypeAttribute(new[] { GetType().GetTypeInfo().Assembly })
In the solution provided above, this assumes the class that contains the function to be evaluated is on the same class the code currently resides in. If the methods are to be used outside of said class, the assembly will need to change.
FindTypesMarkedWithDynamicLinqTypeAttribute(new[] { typeof(AnotherClassName).Assembly })
Nothing changes from the solution above, this is just for clarification for anyone attempting to use it.

As regards the current version (1.2.19) of Dynamic LINQ, you will probably get another exception:
System.Linq.Dynamic.Core.Exceptions.ParseException : Enum value 'Test' is not defined in enum type 'A'
To make DLINQ know your type 'A', you have two options:
Set up parsing config with your own custom types provider where you directly specify the type 'A'.
Mark your type with the attribute [DynamicLinqType]. If that type is loaded into the current domain (that's the usual case), you don't have to do anything more since the default custom type provider already scans the current AppDomain for types marked with [DynamicLinqType]. And only if that's not the case, i.e. your type is not loaded into the current domain, you have to do something like in that answer.
What if you would like to use both approaches - the first for type 'A' and the second for type 'B'? In that case, you just have to "merge" your type 'A' with the default provider types:
public class DynamicLinqTests
{
[Test]
public void Test()
{
var a = new Tuple<int, int>(1, 1);
var b = new[] { a };
var parsingConfig = new ParsingConfig
{
ResolveTypesBySimpleName = true,
CustomTypeProvider = new TestCustomTypesProvider()
};
var queryWithA = b.AsQueryable().Select(parsingConfig, "A.Test(it.Item1)");
queryWithA.ToDynamicList();
var queryWithB = b.AsQueryable().Select(parsingConfig, "B.Test(it.Item1)");
queryWithB.ToDynamicList();
}
public static class A
{
public static int Test(int i)
{
return i++;
}
}
[DynamicLinqType]
public static class B
{
public static int Test(int i)
{
return i++;
}
}
public class TestCustomTypesProvider : DefaultDynamicLinqCustomTypeProvider
{
public override HashSet<Type> GetCustomTypes()
{
var customTypes = base.GetCustomTypes();
customTypes.Add(typeof(A));
return customTypes;
}
}
}

I may be confused but your syntax whereby you are using a string in your Selects doesn't compile for me. The following syntax works:
var q = b.AsQueryable().Select(it => A.Test(it.Item1));

var b = new[]{ a };
The above array is don't know what type of array , and it's not type safe ?
Your values are assigned in variant data type so it's not integer value (I think string value) ,when you get this values in your query must need to convert.toint32() because your class parameter data type is integer
Please try it
var b = new **int**[]{ a };
instead of var b = new[]{ a };
The important hint is here (in bold):
No property or field 'xxx' exists in **type** 'xxx'
And Please look this for previous discussion :
Dynamic Linq - no property or field exists in type 'datarow'

The following works for me:
var a = new Tuple<int, int>(1, 1);
var b = new[] { a };
var q = b.AsQueryable().Select(it=>A.Test(it.Item1));
var q1 = b.AsQueryable().Select(it => Convert.ToInt32(it.Item1));
var q2 = b.AsQueryable().Select(it => (float) it.Item1);

Related

C# list in function param

I'm new to C#. I want to take a list as argument and return another from the data I get from the first one.
private List<DestinationGenericMapProps> ConstructDestinationMapPropsList(List<BoutiqueInWebService> datas)
{
var result = new List<DestinationGenericMapProps>(datas);
return result;
}
I get this error:
Error 241 The best overloaded method match for System.Collections.Generic.List<VDDataUpdaterGeneric.DataObjects.DestinationGenericMapProps>.List(int) has some invalid arguments
I know this is probably pretty basic but I'm new to C# and struggle with this. Thanks for your help.
List<BoutiqueInWebService> is not a List<DestinationGenericMapProps>.
This will not work unless BoutiqueInWebService is derived from DestinationGenericMapProps.
Basically, there is a List<T>(IEnumerable<T>) constructor, but the T's have to be the same.
Either change your return type to List<BoutiqueInWebService> and change your new statement:
private List<BoutiqueInWebService> ConstructDestinationMapPropsList(List<BoutiqueInWebService> datas)
{
var result = new List<BoutiqueInWebService>(datas);
return result;
}
or change your parameter to be of type List<DestinationGenericMapProps>:
private List<DestinationGenericMapProps> ConstructDestinationMapPropsList(List<DestinationGenericMapProps> datas)
{
var result = new List<DestinationGenericMapProps>(datas);
return result;
}
Alternatively, if you know how to make a DestinationGenericMapProps from a BoutiqueInWebService, you can use System.Linq and perform a select against the argument:
private List<DestinationGenericMapProps> ConstructDestinationMapPropsList(List<BoutiqueInWebService> datas)
{
var result = datas.Select(x => new DestinationGenericMapProps() { ... }).ToList();
return result;
}
Your method return type is a list of DestinationGenericMapProps, but you're trying to create list of BoutiqueInWebService (which is data).
You can do this to match your return type:
private List<DestinationGenericMapProps>
ConstructDestinationMapPropsList(List<BoutiqueInWebService> datas)
{
return (from d in datas
select new DestinationGenericMapProps()
{
// map properties here
Prop1 = d.SomePropInData
}).ToList();
}
You're getting the error because you're trying to populate a list of one type (DestinationGenericMapProps) with objects from a list of a different type (BoutiqueInWebService) which isn't type safe.
You can only do this if BoutiqueInWebService inherits from DestinationGenericMapProps.
C# supports function overloading, which means that a class can have more than one function with the same name as long as the parameters are different. The compiler decides which overload to call by compairing the types of the parameters. This applies to constructors too.
The List class has a three overloads of its constuctor:
List<T>()
List<T>(IEnumerable<T>)
List<T>(int)
I assume that you are trying to use the second of those as it will create a new list from the passed in one. For the list you are creating T is a DestinationGenericMapProps. So the constructors are:
List<DestinationGenericMapProps>()
List<DestinationGenericMapProps>(IEnumerable<DestinationGenericMapProps>)
List<DestinationGenericMapProps>(int)
The list you have passed in has T set to BoutiqueInWebService. As such the compiler is trying to find a constructor like this in the list above.
List<DestinationGenericMapProps>(IEnumerable<BoutiqueInWebService>)
As it can't find one it raises the error you have recieved.
Is it possible to cast a BoutiqueInWebService to a DestinationGenericMapProps object? If so you could do this:
var result = datas.Cast<DestinationGenericMapProps>().ToList()
If no direct cast is possible it may be possible to do a long hand cast like this:
var result = datas.Select(o => new DestinationGenericMapProps() { PropA = o.PropA, PropB = o.PropB /* etc */}).ToList();

Create a lambda expression with a new anonymous type at runtime

I want to invoke a method that expects a parameter like this:
Expression<Func<sometype, 'a>> expr
I need to construct this parameter at runtime, because I won't know what the anonymous type will look like before; it could have any amount of fields:
x => new { a=x.a, b=x.b, c=x.c, etc... }
I can create a type at runtime that has the same 'signature' (Is that the correct word for this?) as the desired anonymous type, but the question is: How do I construct this lambda expression at runtime from that? Especially Expression.New is bugging me, because I need to pass a constructorInfo to it that I have to get from an existing type (which can indeed be an anonymous type, but I can't create an anonymous type at runtime. Or is there a way to do that?).
Update (some context as requested in the comments)
The method I want to invoke is:
DependentNavigationPropertyConfiguration.HasForeignKey<TKey>(Expression<Func<TDependentEntityType, TKey>> foreignKeyExpression)
The reason I want to do this is to automatically make a navigation property to an entity that inherits from a certain base class include the key of that base class in the foreign key. Because an entity can have multiple key fields of any type, the type TKey is only known to me at runtime.
Use a separate method:
public static void Main()
{
var myExpression = Express(str => new {
String = str,
Length = str.Length
});
// We can compile/use it as well...
var compiledExpression = myExpression.Compile();
var anonymousOutput = compiledExpression("Input String");
Console.WriteLine(anonymousOutput.String); // Output: Input String
Console.WriteLine(anonymousOutput.Length); // Output: 12
Debug.WriteLine(myExpression); // Output: "str => new <>f__AnonymousType0`2(String = str, Length = str.Length)"
Console.ReadLine();
}
static Expression<Func<String, T>> Express<T>(Expression<Func<String, T>> expression)
{
return expression;
}
Note however, that the starting type (in my example String) must be known up front.
Update:
Since what it sounds like you're trying to do is dynamically create a type, I'll give you a simple example of how to do that.
public static void Main()
{
// Create an anonymous type with two fields
Type myAnonymousType = CreateNewType<String, Int32>();
dynamic myAnon = Activator.CreateInstance(myAnonymousType);
myAnon.FieldA = "A String";
myAnon.FieldB = 1234;
Console.WriteLine(myAnon.FieldA); // Output : "AString"
Console.WriteLine(myAnon.FieldB); // Output : 1234
Console.ReadLine();
}
public static Type CreateNewType<TFieldTypeA, TFieldTypeB>()
{
// Let's start by creating a new assembly
AssemblyName dynamicAssemblyName = new AssemblyName("MyAsm");
AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("MyAsm");
// Now let's build a new type
TypeBuilder dynamicAnonymousType = dynamicModule.DefineType("MyAnon", TypeAttributes.Public);
// Let's add some fields to the type.
FieldInfo dynamicFieldA = dynamicAnonymousType.DefineField("FieldA", typeof(TFieldTypeA), FieldAttributes.Public);
FieldInfo dynamicFieldB = dynamicAnonymousType.DefineField("FieldB", typeof(TFieldTypeB), FieldAttributes.Public);
// Return the type to the caller
return dynamicAnonymousType.CreateType();
}
As you can see, this is a little more complicated. If you want to study the topic further though, definitely reference Reflection.Emit.
Anonymous types are a compiler feature. If you don't get the compiler to create them at compile-time, then you will have to use meta-programming - either TypeBuilder or maybe CSharpCodeProvider. You might be better off using tuples - at least they are easy to create (you can use Tuple.Create easily enough).
As for the expression; I would suggest typing it as Expression<Func<sometype, object>> - which will work for any formulation. The code inspecting the Expression can of course see what the actual type is.
you can do simply like this
context.Students.Join(context.Courses, a => a.Course_id, b => b.Course_id, (a, b) => new { Student= a, Course= b }).Where(x => x.Student_id == studentId)
.Select(y => new
{
StudentId = y.Student.StudentId,
RegistrationNumber = y.Student.RegNo,
Name = y.Student.Name,
Coursename = y.Course.Name
}).ToList();

Passing IEnumerable data from LINQ as parameter to a method [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I pass an anonymous type to a method?
I have the following LINQ Statement, whose output has to be processed in another method:
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new { F=f, T=target };
What should be the datatype of the parameter in the method that will take this data?
You can not return the anonymous data types from a method. You can define a class and return object of that class from query and pass it to target method.
public class SomeClass
{
public string F {get; set;}
public string T {get; set;}
}
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new SomeClass { F=f, T=target };
You can pass the query result IEnumerable<SomeClass> to method as parameter.
public void MethodToCall(IEnumerable<SomeClass> someClass)
{
}
To call the method by passing the query result (IEnumerable<SomeClass>) that is stored in data in this sample code
MethodToCall(data);
You can't very easily pass anonymous types around. You can either create a class, or since your data has only two properties, use a Tuple:
select new Tuple<List<string>, string> (f, target);
If I have the data types correct, then the data type of the parameter would be:
IEnumerable<Tuple<List<string>, string>>
and you would reference F and T using the Tuple properties Item1 and Item2.
1) Just to pass the result of the query, make your function generic, that will do:
var data = from lines in File.ReadAllLines(TrainingDataFile)
.Skip(ContainsHeader ? 1 : 0)
let f = lines.Split(new[] { FieldSeparator }).ToList<String>()
let target = f[TargetVariablePositionZeroBased]
select new { F=f, T=target };
SomeMethod(data);
public void SomeMethod<T>(IEnumerable<T> enumerable)
{
// ^^choose the return type..
}
Simple. If the processing inside the method is something so simple this will do. But you won't be able to access properties F and T inside the method.
To do so:
2) You can use the "cast by example" trick shown here by Eric. To quote him:
We use method type inference and local variable type inference to tell
the compiler "these two things are the same type". This lets you
export an anonymous type as object and cast it back to anonymous type.
...the trick only works if the example and the source objects were
created in code in the same assembly; two "identical" anonymous types
in two different assemblies do not unify to be the same type.
SomeMethod(data);
public void SomeMethod(IEnumerable<object> enumerable)
{
var template = new { F = new List<string>(), T = string.Empty };
foreach (var item in enumerable)
{
var anonymousType = item.CastToTypeOf(template);
//print string.Join(", ", anonymousType.F) + " - " + anonymousType.T //compiles
//or whatever
}
}
//a more generic name perhaps is 'CastToTypeOf' as an extension method
public static T CastToTypeOf<T>(this object source, T example) where T : class
{
return (T)source;
}
The catch here is that SomeMethod now is tailor made for your anonymous type, since you're specifying a specific type inside the method, so its better to not make the function generic (though you can do) and to give a suitable name for the function.
3) If function is just for your unique type now, I would better have them all wrapped in a single method and not pass at all - no hassle! :)
4) Or you can delegate the action to be done on your anonymous type. So method signature would be like:
SomeMethod(data, d => print string.Join(", ", d.F) + " - " + d.T);
public void SomeMethod<T>(IEnumerable<T> enumerable, Action<T> actor)
{
foreach (var item in enumerable)
actor(item);
}
If it matters you can have Func delegate as well by having one more type argument.
5) Rely on fiddly reflection to get the properties from your anonymous type otherwise.
6) Use dynamic keyword on method argument and now you have dynamic typing. Both the above doesnt give you benefits of static typing.
7) You will be better off having a separate class that holds F and T. And that the best of all. But ask yourself do they together represent something as an entity?
8) If not, just pass an IEnumerable<Tuple> or IDictionary depending on what matters.
It all depends on what/how you want to achieve with the method. Personally, I would go for the approach 2 in a hobby project (for the fun involved), but in production code 3, 4, 7, 8 depending on the context.

the type of var (without using dynamics)? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I pass an anonymous type to a method?
Im trying to recognize the type of the anonymous type.
List<int> lst = new List<int> {1, 2, 3, 4, 5};
var myVarType = from item in lst select new {P = item*item, P2 = item + "###"};
foreach (var k in myVarType)
{
Console.WriteLine(k.P + " " + k.P2);
}
Now i want a part of code to be transferred to a function but it screams that he doesnt know the type - which is logical since var is to be known at compile time and he doesnt know the type at compile :
I dont want to use dynamic || Tuples.
and as you know var is not acceptable as a func param type.
But , Ive once read that there is a trick which lets me transfer to myFunc the anonymous type .
I think it was by Jon skeet or Eric lippert.
Help ?
edit
look at my self answer.
I found it here
What's the return type of an anonymous class
The type is 'generated' and you might be able to get it at run-time with reflection but it will contain characters you can't use in a name.
You could use Tuples:
select new Tuple<int,string> ( item*item, item + "###");
Make the method generic, this should work.
static void MyFunc<T>(IEnumerable<T> myVarType) ...
Edit
As mentioned in comments you can't access the properties. You could use here a delegate to access the properties or use dynamic ( which you don't want to use ).
static void MyFunc<T>(IEnumerable<T> myVarType, Func<T, Object[]> argumentCreator)
{
Console.WriteLine("{0} {1}", argumentCreator(myVarType));
}
here is the code which i found
What's the return type of an anonymous class
static T CastByExample<T>(object source, T example) where T : class
{
return source as T;
}
static object ReturnsAnonymous() { return new { X = 123 }; }
static void DoIt()
{
object obj = ReturnsAnonymous();
var example = new { X = 0 };
var anon = CastByExample(obj, example);
Console.WriteLine(anon.X); // 123
}

C# What construct am I Looking for Lamba / Expression / Func / Reflection for runtime property substitution?

I've a method on a generic base class that I want to execute for all superclasses of it
The logic is something like:
BuildAverageDateStats(List<type> items, DateProperty1 exp, DateProperty2 exp2)
{
return new Stat{
Value = items.Average(c => (c.DateProperty2 - c.DateProperty1).Milliseconds)
};
}
myobject.BuildAverageDateStats(list, () => c.QueuedDate, () => c.CompletedDate);
myobject.BuildAverageDateStats(list, () => c.ActionedDate, () => c.CompletedDate);
I think I need expressions, but not sure how...
I could send it in as Func i.e. Value = items.Average(c => myfunc(c)) but looking for a property substitution example.
Stat BuildAverageDateStats<U>(List<type> items, Func<U, double> exp)
where U:type
{
return new Stat{
Value = items.OfType<U>().Average(exp);
};
}
You can call it like this
BuidlAverageDateStats<Dog>(items, d=>d.Age - d.Height);
Though my example doesn't make sense.
If you are really only ever going to use one of the three DateTime properties that you have right now, I would keep the method signature the way you have it right now.
To make things neater, make some public static readonly delegate fields on your class for your properties, and use those, instead of writing the same expression time and time again:
public static readonly DateSelector Date1Property = delegate(CompareTest c) { return c.Date1; };
public static readonly DateSelector Date2Property = delegate(CompareTest c) { return c.Date2; };
public static readonly DateSelector Date3Property = delegate(CompareTest c) { return c.Date3; };
If, on the other hand, you expect inheriting classes to implement more properties than the three you have right now, you could consider passing in the properties as String and using the Dynamic Linq Library (and build a dynamic expression that returns the property) or a DynamicMethod to return your property. Both would have the benefits of reflection with the painful performance. If you need it, I have some code laying around for that.
Type safety will be out the window though, so I wouldn't use it unless necessary, and it sounds like it isn't.
Menno
static Stat BuildAverageDateStats<T>(List<T> items, string pname1, string pname2){
return new Stat {
Value = items.Average( c =>
{
var ty = c.GetType();
var pv1 = (dynamic)ty.GetProperty(pname1).GetValue(c,null);
var pv2 = (dynamic)ty.GetProperty(pname2).GetValue(c,null);
return pv2 - pv1;
})
};
}

Categories