Dynamic Linq cannot parse long.Parse() - c#

I'm using the Dynamic Linq Library to parse a boolean expression. In this method:
public static LambdaExpression Parse(SearchQuery query)
{
string compilableExpression = BuildCompilableExpression(query);
ParameterExpression parameter = System.Linq.Expressions.Expression.Parameter(typeof(EventListItem));
return System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { parameter }, null, compilableExpression);
}
BuildCompilableExpression returns this string:
"long.Parse(InstanceID.ToString()) == long.Parse(\"2\")"
Which is correct (InstanceID is a property in the EventListItem), however, the call to ParseLambda() failes with this exception:
No property or field 'long' exists in type 'EventListItem'
I've tried parsing an expression that contains string.Compare() and that works just fine, so I don't understand why long.Parse()doesn't work. I was just wondering if anyone has ever done this. Any help is appreciated.

long isn't the name of a type, it is a shortcut provided by C#. Int64 is the technical name, have you tried that? Similarly String is the name of the string type.
Note that string might have worked because while C# is case sensitive, the analyzer may or may not be.

The type long does not exist in .NET. long is a C# keyword and is an alias for the .NET type System.Int64. Try using Int64.Parse(...).

Related

Parse an object to a string representation c#

I'm trying to parse my variable to its string representation typeName.
string typeName = property.PropertyType.ToString();
var propertyItem = (typeName)property.GetValue(templateData, null);
The string typeName should be the 'Type' of the property I have in my Model so somehow i want to parse it to that type. (at this moment it is List(InvoiceModel), but this may vary)
I hope this is enough information, otherwise please notify me. Thanks in advance.
property.GetValue returns the required object. From your code sample it seems that you don't know the object's type at compile time.
It is not possible to cast that object using (typename), and there is no use, because still you won't know the real type at compile time.
What you probably want to do is to use dynamic:
dynamic propertyItem = property.GetValue(templateData, null);
I think what you are looking for is property.GetType().ToString();
though you can't just put the varable in brackets to convert you need to use reflection to create the type
That said this entire idea is a bad idea, from the look of your code i think your trying to create some form of MetaData, if so then i would use an Enum to define your allowed datatypes, and i would only allow the simplest ones int, double, string, datetime etc and possibly an array's of such
in that case you would then do,
if(Property.Type == AllowedTyoes.String)
{
string stringval = Property.Value as string;
//use the string for a string safe function
}
if(Property.Type == AllowedTyoes.Int)
{
string stringval = Property.Value as string;
int tmp;
if(int.TryParse(stringval,out tmp))
{
//use the int for a int safe function
}
}

Expression.Call, Int32 and Enum

Can't figure out how to build an expression that compares an enum type with an int. I have a MVC site with Kendo components embedded. In the view-class, the property is an ENUM, but the view returns an Int32 (the source is a Kendo IFilterDescriptor).
So the problem is...: I receive an int from the view, build the expression, that fails because an enum is expected. Fix this by converting the int to its enum representation, but then it fails when querying the database, because the database expect an Int32.
public static Expression<Func<DOMAIN, bool>> GetExpressionsFromFilterDescription<DOMAIN, VIEW>(this IEnumerable<IFilterDescriptor> _this)
{
Expression expressions = null;
ParameterExpression pe = Expression.Parameter(typeof(DOMAIN), "x");
foreach (FilterDescriptor item in _this)
{
MemberExpression member = Expression.Property(pe, item.Member);
ConstantExpression value = Expression.Constant(item.Value);
Expression exp = null;
switch (item.Operator)
{
case FilterOperator.IsEqualTo:
exp = Expression.Equal(member, value);
From what I understand, Expression.Call() should be able to fix this, I just can't figure out how to do this.
Any help would be appreciated.
BR Peter
UPDATE
Converting the value like below, does fix the expression problem (the "The binary operator Equal is not defined for the types..." error), but then I get a new error querying the database: "Type mismatch in NHibernate.Criterion.SimpleExpression: Status expected type System.Int32, actual type...".
exp = Expression.Equal(member, Expression.Convert(value, typeof(MyEnum)));
The fix, as I see it, is either by building my own compare (Expression.Call ?) or by telling that the type (in item.Member) is an int and not an enum, but I don't know how or if this is the right way.
Thanks.
UPDATE UPDATE
It seems like that the second part of the problem is due to NHibernate.QueryOver and its limitations. Once changed to NHibernate.Linq, the query part of the problem, went away.
As for the Expression part I have fixed the problem by adding an attribute to the property telling how the value should be converted. I am not using Expression.Convert (but I could have), the conversion happens in the received filter description before building the expression.
Thanks for your time and help. I will accept the answers related to Expression.Convert since it could fix the problem. I still do want to understand the Expression.Call() method - so please feel free to comment on that. Thanks.
Wouldn't this do the trick?
MemberExpression member = Expression.Convert(
Expression.Property(pe, item.Member), typeof(int);
ConstantExpression value = Expression.Constant((int)item.Value);
You can use Expression.Convert to convert an expression of an enumtype to anint` (assuming that the underlying type of the enum is an int).
I don't exactly see your enum you are comparing to, is it item.Value?
You can always cast the value of an enum to a number to compare it to a number or feed it into systems that don't recognize enums:
enum Blah
{
Tom,
Rick,
Harry
}
if ((Int32)Blah.Tom == 0)
{
}

Wrapper around a C# lambda expression

Background:
I am creating a COM library and would like to use a modified version of code from this answer. I would like to pass an object to WhatsMyName COM function and return a string representation. I am not entirely sure this is yet possible but trying doesn't hurt ;)
This is how I am seeing it:
Dim myComInst as new MyComLib
MsgBox myComInst.WhatsMyName(myComInst)
and expecting myComInst to be returned.
I am stuck at wrapping the below function so it doesn't take an expression but an object parameter.
public static class MemberInfoGetting
{
public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
{
MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
return expressionBody.Member.Name;
}
}
And I can use it like this
string testVariable = "value";
string nameOfTestVariable = MemberInfoGetting.GetMemberName(() => testVariable);
which is rather straight forward.
What I am trying to do is to create a wrapper around it so I can pass any object instead of using the lambda expression in the parameter.
So instead of () => testVariable I'd like to pass just any object.
I have tried to wrap it like this
public string WhatsMyName(object objInstance)
{
return MemberInfoGetting.GetMemberName(() => objInstance);
}
but it returns objInstance instead of the object I am passing to the function.
I have tried to use (forgive me) a ref keyword but it doesn't work with lambda expressions.
If any one can first verify whether what I am trying is possible or not that would be great! If it is, then please guide me or point to references about writing a wrapper function for a lambda expression.
You time and help highly appreciated!
If you pass in the actual expression, rather than an Expression object that represents it, then the expression is being evaluated to its value before it is passed to the function. By the time you're inside the function it is too late to access that information. Using an Expression is passing all of the information used to represent that expression, rather than just its value, which is why you can access it from inside of that function.

Can't write string from table to string attribute in C#

I read values from an local Access mdb-file. One value is stored as string in the db and I have it in a table. When using the GetType() method it return "System.String" and I can print it on the console without a problem but when I want to use it as an attribute for another method (requires a string) I get an error ("Cannot convert from 'object' to 'string'" and the same for 'int'). The same problems occur with some int values.
Am I doing something wrong or what is the problem in that case?
Console.WriteLine(dt.Rows[0][ProjName]); //prints project_name
Console.WriteLine(dt.Rows[0][ProjName].GetType()); //print "System.String"
Project = new Project(dt.Rows[0][ProjName], dt.Rows[0][MinDay], dt.Rows[0][MinWeek], dt.Rows[0][DayWeek]); //Error
Project = new Project(Convert.ToString(dt.Rows[0][ProjName]), Convert.ToInt32(dt.Rows[0][MinDay]), Convert.ToInt32(dt.Rows[0][MinWeek]), Convert.ToInt32(dt.Rows[0][DayWeek])); //Works Fine
Constructor for the Project Class:
public Project(string projectName, int hoursPerDay, int hoursPerWeek, int daysPerWeek)
You have stated in your answer is works when converting, and it is necessary as they are not strings and integers. They are objects. You can create a methid to handle it if you want.
public Project CreateProject(object projectName, object hoursPerDay, object hoursPerWeek, object daysPerWeek)
{
return new Project(projectName.ToString(), Convert.ToInt32(hoursPerDay), Convert.ToInt32(hoursPerWeek), Convert.ToInt32(daysPerWeek);
}
You have to explicitly cast the objects:
To cast to string use:
Object.ToString();
To cast to integers use:
Int32.TryParse(String, out int);
Your constuctor becomes
Project = new Project(dt.Rows[0][ProjName].ToString(), Int32.Parse(dt.Rows[0][MinDay]), Int32.Parse(dt.Rows[0][MinWeek]), Int32.Parse(dt.Rows[0][DayWeek]));
Note: Using Int32.Parse instead of Int32.TryParse assumes that the argument provided is a valid int at all times and does not give you a way to check if the casting has succeeded.
dt.Rows[0][ProjName] returns type object, and your method expects string. Even though you know it to be a string, it is not obvious to the compiler and must be specified explicitly using a cast, as you show in your last example, although just casting should be more efficient than converting unnecessarily:
Project = new Project((string)dt.Rows[0][ProjName], ...

How to convert a Object String to Object Guid in C#

I have a DetailsView, I need get the value specifield in DataKeyNames "UserId" (a Guid Field) and add it to an Object Guid.
At the moment I am using this code:
String myUserId = (String)uxAuthorListDetailsView.DataKey["UserId"].ToString();
but I would need something like:
Guid myUserGuid = (Guid)uxAuthorListDetailsView.DataKey["UserId"].ToString();
But does not work I get error Error
Cannot convert type 'string' to 'System.Guid'
What could be the problem? Thanks guys for your support!
Well, the problem is that you're calling ToString() and then trying to cast that string to a Guid, when there's no such conversion available. Possible alternatives:
Cast instead of calling ToString(), if the original value is really a Guid:
Guid guid = (Guid)uxAuthorListDetailsView.DataKey["UserId"];
Parse the string instead:
Guid guid = new Guid(uxAuthorListDetailsView.DataKey["UserId"].ToString());
If this is user-entered data at all, or there's any other reason why the value is half-expected to be incorrect, and if you're using .NET 4, you might want to use Guid.TryParse instead, which will allow you to handle failure without an exception.
var myUserGuid = new Guid(uxAuthorListDetailsView.DataKey["UserId"].ToString());
Check under debug: what object is uxAuthorListDetailsView.DataKey["UserId"]
I guess this must be already the Guid; and conversion is not needed
Assuming uxAuthorListDetailsView.DataKey["UserId"] stores a valid Guid
try this
Guid myUserGuid = (Guid)uxAuthorListDetailsView.DataKey["UserId"]
remove ToString method

Categories

Resources