Basically I have some code where when it happens, I need to set some object equal to some expression. All of this "what to do" jazz is stored as a string. So I parse it, and use reflection to find the object I am doing it to. Now I need to find out how to store the value to this object. The problem is the value could be "1", "1*(5/2)", or "some string value". It would be really cool if I could have expressions like "this.SomeProperty" or "(x > 3 ? 4 : 5)".
Also, the object it is storing to, could be a string, int, double, or float at the minimum.
The VS2008 samples included a nifty ExpressionParser which could be used as a generic expression parser (VS2008 Samples). With a few small updates, and a custom factory class, we can turn it into something a bit more expressive:
string expression = "(1 + 2)";
var func = FunctionFactory.Create<int>(expression);
Or:
expression = "(a * b)";
var func2 = FunctionFactory.Create<int, int, int>(expression, new[] { "a", "b" });
The return types of these Create methods are Func<> instances, which means we get nice strongly type delegates:
int result = func2(45, 100); // result = 450;
I've push the code to a gist
Update: I've recently blogged about this too.
Update 2, another example:
var person = new Person { Age = 5 };
string expression = "(Age == 5)";
var func3 = FunctionFactory.Create<Person, bool>(expression);
bool isFive = func3(person); // Should be true.
Have you seen http://ncalc.codeplex.com ?
It's extensible, fast (e.g. has its own cache) enables you to provide custom functions and varaibles at run time by handling EvaluateFunction/EvaluateParameter events. Example expressions it can parse:
Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)");
e.Parameters["Pi2"] = new Expression("Pi * Pi");
e.Parameters["X"] = 10;
e.EvaluateParameter += delegate(string name, ParameterArgs args)
{
if (name == "Pi")
args.Result = 3.14;
};
Debug.Assert(117.07 == e.Evaluate());
It also handles unicode & many data type natively. It comes with an antler file if you want to change the grammer. There is also a fork which supports MEF to load new functions.
Related
In Visual Basic, there is this IIF Function, as in Crystal Report, etc ...
In C # itself, this function does not exist, but it is the same as doing something like this:
bool a = true;
string b = a ? "is_True" : "is_False";
But for the code to be a bit easier to read I wanted to do it as a function for C #, leaving it like this:
public static T IIf<T>(bool expression, T truePart, T falsePart)
{
return expression ? truePart : falsePart;
}
Or to not operate with the real values can also be done using delegates, to access the necessary values:
public static T IIf<T>(bool expression, Func<T> truePart, Func<T> falsePart)
{
return expression ? truePart() : falsePart();
}
So far this works well ...
But how can I modify this function so I can take 2N + 1 arguments?
(N - the number of logical expressions specified)
Example the desired result:
Each odd argument specifies a logical expression;
Each even argument specifies the value that is returned if the previous expression evaluates to true;
The last argument specifies the value that is returned if the previously evaluated logical expressions yielded false.
int value = IIf(Name = "Joel", 1, Name = "Peter", 2, Name = "Maria", 3, 4);
Can someone give me a hand with this?
Environment: C # - Visual Studio 2017
First off, as noted in the comments, this is a bad idea. Newer versions of C# already support pattern-matching switches as a built-in feature of the language; use it.
Second, this is a bad idea because the API of "argument, case1, result1, case2, result2, ..." has a signature that is hard to express in the C# type system.
Were I forced to implement such an API, I would suggest using tuples:
public static R Switch<A, R>(
A item,
R theDefault,
params (A, R)[] cases )
{
foreach(var c in cases)
if (item.Equals(c.Item1))
return c.Item2;
return theDefault;
}
Or, make a helpful utility method and use it:
public static T FirstOrDefault(
this IEnumerable<T> items,
T theDefault,
Func<T, bool> predicate)
{
foreach(var i in items.Where(predicate))
return i;
return theDefault;
}
public static R Switch<A, R>(
A item,
R theDefault,
params (A, R)[] cases ) =>
cases.FirstOrDefault(
(item, theDefault),
c => item.Equals(c.Item1)).Item2;
If you cannot use tuples because you're using an older version of C#, you could make your own pair type or use the key-value pair type.
But just do not go there. If you need a switch, write a switch. If you need a dictionary, write a dictionary.
If you want to preserve the order of your parameters, which presumably you do if you're trying so hard to make the function replicate what you've seen elsewhere, then you can write something like this:
public T IIf<T>(params object[] objects) {
for(var i = 0; i < objects.Length - 1; i += 2)
if((bool)objects[i])
return (T)objects[i+1];
return (T)objects[objects.Length - 1];
}
But it's a good lesson in why you would avoid something like this. Firstly, you have to explicitly declare the type you're working with. So you'd have to use it like this:
var value = IIf<int>(Name == "Joel", 1, Name == "Peter", 2, Name == "Maria", 3, 4);
Notice the passing of 'int' as a type parameter. You can avoid that by changing the order of the parameters so that the default comes first.
But, if you're just willing to adopt a personal pattern, the nested ternary syntax can be quite readable:
var value =
Name == "Joel" ? 1
: Name == "Peter" ? 2
: Name == "Maria" ? 3
: 4;
If you don't feel it's readable, then it's just because it takes some getting used to. Imagine going the other way, from a C# developer to VB, and seeing 'IIF'. You'd be thinking, "why do they add the extra 'I' in 'IF'?". I should make a function "IF" that emulates "IIF". But that would be a bad idea, wouldn't it?
I am looking for a way to get a boolean value from a string.
I have a string, stored in a database, that is a condition to be tested with.
suppose the string = "[number] < 10000"
In my code I then plan to replace [number] with a actual number so the string would become "100 < 10000".
Is there a simple way to evaluate this string to a boolean.
In this case it would be False.
Another example: "[number] > 100 && [number] < 1000"
If number would be 200, the evaluation would be True.
What if I add code to this condition, like "if ([number] > 100 && [number] < 1000) { return true;} else {return false;}"
If there a simple way to get the return value from this string with code?
You can make use of DynamicExpression class, it is available in this nuget package. It can evaluate expressions on the fly.
Below is an example,
var expression = System.Linq.Dynamic.DynamicExpression.ParseLambda(
new System.Linq.Expressions.ParameterExpression[] { },
typeof(bool),
"100 > 1000",
new object[] { });
var compiledDelegate = expression.Compile();
var result = compiledDelegate.DynamicInvoke(null);
The result will be false as the provided expression "100 > 1000" is false.
If you need more control, you have to create expressions depending upon dynamic strings representing logical operations. For example, I have taken your first case of "[number]<1000" You can try below:
static void Main(string[] args)
{
string code = "[number] < 10000".Replace("[number]", "100");
string[] operands = code.Split('<');
var comparison = Expression.LessThan(
Expression.Constant(operands[0]),
Expression.Constant(operands[1]));
var lambda = Expression.Lambda<Func<bool>>(comparison).Compile();
bool result = lambda();
}
Or Alternatively you can use existing libraries or nuget packages for doing same thing in a more simpler way (under hood they do same though):
string code = "[number] < 10000".Replace("[number]", "100");
func = ExpressionParser.Compile<Func<bool>>(code);
bool result = func()
It makes use of Lambda parser as shown here
Lets say i have
int a = 1;
int b = 2;
string exp = "b > a";
and i want to evaluate the string expression with those variables
if(exp.SomeKindOfParseOrCast())
{
//here be magic
}
Is it possible in any simple way?
Nope, not in C# - these are parameter names, and thus are compile time values, and this expression parsing you are describing is done in runtime - the computer doesn't know the name of the parameters while it's being evaluated. Instead, you could do something a little more strict, like an expression parser - implement your own way to parse string expressions.
Very very simplified:
if(exp.Equals("b > a"))
{
if(b>a)
// do what you do if b is bigger than a
else
// do what you do with a wrong expression
}
else if (exp.Equals("a > b")
{
if(a>b)
// do what you do if a is bigger than b
else
// do what you do with a wrong expression
}
else if (exp.Equals("a = b")
{
if(a==b)
// do what you do if a is equal to b
else
// do what you do with a wrong expression
}
else
// do what you do with a badly formatted expression
if you would like to take this a step forward, you can cut spaces, make sure the expression is lowercase, etc. - there's many examples around, I personally like this one.
Is it possible in any simple way?
No, in C# this is not possible in a simple way like it were in languages such as JavaScript with its eval function. Anyway, you'd have to provide bindings of in-expression parameters to actual values.
You can use Roslyn.
Here is an example of how to compile and run your own code in runtime.
Disclaimer: I'm the owner of the project Eval Expression.NET
This library is very easy to use and allow to evaluate and compile almost all the C# language.
// For single evaluation
var value1 = Eval.Execute<bool>("b > a", new { a = 1, b = 2 });
// For many evaluation
var compiled = Eval.Compile<Func<int, int, bool>>("b > a", "a", "b");
var value2 = compiled(1, 2);
When I use Expression.ToString() to convert an Expression Tree into human readable form, the result is something like this:
x => ((x.ID > 2) OrElse (x.ID != 6))
x => ((x.ID > 2) AndAlso (x.ID != 6))
Ideally, I would want the output to show the operators instead of "OrElse" and "AndAlso":
x => ((x.ID > 2) || (x.ID != 6))
x => ((x.ID > 2) && (x.ID != 6))
As a workaround, I could use the string.Replace() method..
.Replace("AndAlso", "&&")
.Replace("OrElse", "||")
but that has obvious weaknesses and seems awkward.
Also I do not want to create a large 'Replace'-section or huge regex-tree simply to get the formatting right.
Is there a simple way to get a code-like human-readable form of expression trees?
Unfortunately the simplest way to do this correctly would be to write your own ExpressionVisitor class which produces the C#-formatted output code.
The simplest way to do this is to use the ExpressionStringBuilder from the reference sources as a starting point and to tweak it until you are happy with the output result.
When I'm interested in the semantics of the code represented by the expression, rather than the exact syntax tree, I've found it very useful to compile it to an Assembly and view that in ILSpy. Convenience method:
// Code is probably adapted from some other answer, don't remember
public static void CompileToAssemblyFile(
this LambdaExpression expression,
string outputFilePath = null,
string assemblyAndModuleName = null,
string typeName = "TheType",
string methodName = "TheMethod",
// Adjust this
string ilSpyPath = #"C:\path\to\ILSpy.exe")
{
assemblyAndModuleName = assemblyAndModuleName ?? nameof(CompileToAssemblyFile);
outputFilePath = outputFilePath ??
Path.Combine(
Path.GetTempPath(),
$"{assemblyAndModuleName}_{DateTime.Now:yyyy-MM-dd_HH_mm_ss}_{Guid.NewGuid()}.dll");
var domain = AppDomain.CurrentDomain;
var asmName = new AssemblyName {Name = assemblyAndModuleName};
var asmBuilder = domain.DefineDynamicAssembly(
asmName,
AssemblyBuilderAccess.RunAndSave,
Path.GetDirectoryName(outputFilePath));
string outputFileName = Path.GetFileName(outputFilePath);
var module = asmBuilder.DefineDynamicModule(
assemblyAndModuleName,
outputFileName,
true);
var typeBuilder = module.DefineType(typeName, TypeAttributes.Public);
var methodBuilder = typeBuilder.DefineMethod(
methodName,
MethodAttributes.Public | MethodAttributes.Static,
expression.ReturnType,
expression.Parameters.Select(p => p.Type).ToArray());
var pdbGenerator = DebugInfoGenerator.CreatePdbGenerator();
expression.CompileToMethod(methodBuilder, pdbGenerator);
typeBuilder.CreateType();
asmBuilder.Save(outputFileName);
Process.Start(ilSpyPath, outputFilePath);
}
(This is not very faithful to the syntax tree because it goes through both the Expression -> IL translation done by the LambdaCompiler, and the IL -> C# decompilation by ILSpy. OTOH, it can improve readability by converting some gotos into loops, and by producing actual C#.)
This will fail if the Expression contains "non-trivial constants" (live objects); but for that one could write a visitor that replaces constants by new variables and then lambda-abstracts these variables at the toplevel.
I get from an input a group of double variables named: weight0, weight1...weight49.
I want to dynamically insert them into a double Array for easier manipulation.
But instead of calling each one like: Weights[0] = weight0...Weights[49] = weight49 I want to do it with a single loop.
Is there a way to do it?
No, basically - unless you mean at the same time that you create the array:
var weights = new[] {weight0, weight1, weight2, ... , weight48, weight49};
Personally, I'd be tempted to get rid of the 50 variables, and use the array from the outset, but that may not be possible in all cases.
you could use reflection to determine the index of the array from the variable names but this is far from efficient. See this post for details.
I would try to do it with a KeyValuePair- Listobject
// sample data
var weight = 1.00;
// create a list
var tmp = new List<KeyValuePair<string,object>>();
// Here you can add your variables
tmp.Add(new KeyValuePair<string,object>("weights" + tmp.Count.ToString()
, weight));
// If needed convert to array
var weights = tmp.ToArray();
// get the information out of the array
var weightValue = weights[0].Value;
var weightKey = weights[0].Key;
I think this will give you all the options, you might need for the array. Give it a try.
I'm putting this up because you can do it - so long as these variables are actually fields/properties. Whether you should is another matter - this solution, while reusable, is slow (needs delegate caching) and I have to say I agree with Marc Gravell - consider using an array throughout if you can.
If the variables are properties then it needs changing. Also if you need to write the array back to the variables in one shot (because this solution generates an array with copies of all the doubles, I wouldn't consider creating an object array with boxed doubles), that requires another method...
So here goes. First a holy wall of code/extension method:
//paste this as a direct child of a namespace (not a nested class)
public static class SO8877853Extensions
{
public static TArray[] FieldsToArray<TObj, TArray>(this TObj o,string fieldPrefix)
{
if(string.IsNullOrWhiteSpace(fieldPrefix))
throw new ArgumentException("fieldPrefix must not null/empty/whitespace",
"fieldPrefix");
//I've done this slightly more expanded than it really needs to be...
var fields = typeof(TObj).GetFields(System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic)
.Where(f =>f.Name.StartsWith(fieldPrefix) && f.FieldType.Equals(typeof(TArray)))
.Select(f =>new{ Field = f, OrdinalStr = f.Name.Substring(fieldPrefix.Length)})
.Where(f => { int unused; return int.TryParse(f.OrdinalStr, out unused);})
.Select(f => new { Field = f.Field, Ordinal = int.Parse(f.OrdinalStr) })
.OrderBy(f => f.Ordinal).ToArray();
//doesn't handle ordinal gaps e.g. 0,1,2,7
if(fields.Length == 0)
throw new ArgumentException(
string.Format("No fields found with the prefix {0}",
fieldPrefix),
"fieldPrefix");
//could instead bake the 'o' reference as a constant - but if
//you are caching the delegate, it makes it non-reusable.
ParameterExpression pThis = Expression.Parameter(o.GetType());
//generates a dynamic new double[] { var0, var1 ... } expression
var lambda = Expression.Lambda<Func<TObj, TArray[]>>(
Expression.NewArrayInit(typeof(TArray),
fields.Select(f => Expression.Field(pThis, f.Field))), pThis);
//you could cache this delegate here by typeof(TObj),
//fieldPrefix and typeof(TArray) in a Dictionary/ConcurrentDictionary
return lambda.Compile()(o);
}
}
The extension method above will work on any type. It's generic over both the instance type and desired array type to simplify the creation of the lambda in code - it doesn't have to be generic though.
You pass in the name prefix for a group of fields - in your case "weight" - it then searches all the public and private instance fields for those with that prefix that also have a suffix which can be parsed into an integer. It then orders those fields based on that ordinal. It does not check for gaps in the ordinal list - so a type with weight0 and weight2 would work, but would only create a two-element array.
Then it bakes a dynamic piece of code using Expression trees, compiles it (at this point, as mentioned in the code, it would be good to cache the delegate against TObj and TArray for future use) and then executes it, returning the result.
Now add this to a test class in a standard unit test project:
private class SO8877853
{
private double field0 = 1.0;
private double field1 = -5.0;
private double field2 = 10.0;
public double[] AsArray()
{
//it would be nice not to have to pass both type names here - that
//can be achieved by making the extension method pass out the array
//via an 'out TArray[]' instead.
return this.FieldsToArray<SO8877853, double>("field");
}
}
[TestMethod]
public void TestThatItWorks()
{
var asArray = new SO8877853().AsArray();
Assert.IsTrue(new[] { 1.0, -5.0, 10.0 }.SequenceEqual(asArray));
}
Like I say - I'm not condoning doing this, nor am I expecting any +1s for it - but I'm a sucker for a challenge :)