Invoking Method with parameters - c#

I am writing a very simple scripting tool with my own functions.
I can invoke methods just fine with and without parameters. My main issue is parsing the parameters that the user input.
do I need to hardcore a parser myself or is there a better way to do so?
sample code
public class FunctionList
{
public void MyMethod(string x)
{
MessageBox.Show(x);
}
}
public void Test()
{
Type type = typeof(FunctionList);
MethodInfo method = type.GetMethod(debugBox.Text);
FunctionList c = new FunctionList();
method.Invoke(c, new object[] { "lorem ipsum" });
}
Example user input in TextBox:
MyMethod(Hello World)
Sleep(500)
MyMethod(Waited 500 ms)
Sum(5, 4)
I will also want to add in conditions and loops, but i think that would require something other then invoking methods.
Example of what i came up with as a parser:
public void Test()
{
Type type = typeof(FunctionList);
MethodInfo method = type.GetMethod(helper.GetUntilOrEmpty(debugBox.Text, "(")); //gets all text until first ( which translates to the function name
FunctionList c = new FunctionList();
//Handles one argument, gets the text between ( )
int pFrom = debugBox.Text.IndexOf("(") + "(".Length;
int pTo = debugBox.Text.LastIndexOf(")");
string result = debugBox.Text.Substring(pFrom, pTo - pFrom);
//pass params
method.Invoke(c, new object[] { result });
}

I have a lot of experience in dealing with such scenarios. I developed my own scripting engine (back in Adobe Flash golden age).
If you have a complex mechanism to create functions and objects than I will recommend you to write a parser that translates your custom scripting code into C#'s compile time error free code.
I have tested your code and it works fine if you already know which parameter you are gonna pass.
public void Test()
{
Type type = typeof(FunctionList);
MethodInfo method = type.GetMethod("MyMethod");
FunctionList c = new FunctionList();
// if you dont know the type of parameter passed then you have to write a parser to determine the type of the parameter right before executing the method.
method.Invoke(c, new object[] { "lorem ipsum" , 10});
}
}
public class FunctionList
{
public void MyMethod(string x, int y)
{
MessageBox.Show(x + " : " + y);
}
}

Related

Passing parameter to a method and assigning to type Func<bool>

I currently have a method like that resembles this
public static bool test(string str);
I would like to assign this method to this type
Func<bool> callback
I am trying to do this (which is incorrect)
callback = test("Str");
The above is incorrect as C# things i am calling a method. How can I tell it to call that method with the parameter Str ? in C++ we can do this
std::function<...,..,"str">
How do we do something similar in C# ?
If your goal is to invoke the callback always using the same string argument (and not a different argument each time), you can declare it like:
Func<bool> callback = () => test("Str");
var result = callback();
But if you are intending to pass a different string value each time, then you need a Func<string, bool>:
Func<string, bool> callback = s => test(s);
var result = callback("Str");
you should declare the function as:
Func<string, bool> callback
to indicate the method it references consumes a string and returns a bool.
then at a later point you can do:
callback = s => test(s);
or inline:
Func<string, bool> callback = s => test(s);
Let me see if I know what you're getting at. In C++ we have 'function pointers' and they are declared with a particular signature. To make the equivalent of that in C# use the delegate keyword.
Here's a quick functional code example:
class DelegateExample
{
// A delegate is a prototype for a function signature.
// Similar to a function pointer in C++.
delegate bool MyDelegate(string[] strings);
// A method that has that signature.
bool ListStrings(string[] strings)
{
foreach (var item in strings)
{
Console.WriteLine(item);
}
return strings.Length > 0; // ... for example
}
// Different method, same signature.
bool Join(string[] strings)
{
Console.WriteLine(string.Join(", ", strings));
return strings.Length > 0; // ... for example
}
public void TryIt()
{
string[] testData = { "Apple", "Orange", "Grape" };
// Think of this as a list of function pointers...
List<MyDelegate> functions = new List<MyDelegate>();
functions.Add(ListStrings); // This one points to the ListStrings method
functions.Add(Join); // This one points to the Join method
foreach (var function in functions)
{
bool returnVal = function(testData);
Console.WriteLine("The method returned " + returnVal + Environment.NewLine);
}
}
}
You can run the sample in a console app like so:
class Program
{
static void Main(string[] args)
{
new DelegateExample().TryIt();
Console.ReadKey();
}
}
Which gives this output:
Apple
Orange
Grape
The method returned True
Apple, Orange, Grape
The method returned True
Hope this is helpful!

Get name of variable in extension Method [duplicate]

Let me use the following example to explain my question:
public string ExampleFunction(string Variable) {
return something;
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(WhatIsMyName);
When I pass the variable WhatIsMyName to the ExampleFunction, I want to be able to get a string of the original variable's name. Perhaps something like:
Variable.OriginalName.ToString() // == "WhatIsMyName"
Is there any way to do this?
What you want isn't possible directly but you can use Expressions in C# 3.0:
public void ExampleFunction(Expression<Func<string, string>> f) {
Console.WriteLine((f.Body as MemberExpression).Member.Name);
}
ExampleFunction(x => WhatIsMyName);
Note that this relies on unspecified behaviour and while it does work in Microsoft’s current C# and VB compilers, and in Mono’s C# compiler, there’s no guarantee that this won’t stop working in future versions.
This isn't exactly possible, the way you would want. C# 6.0 they Introduce the nameof Operator which should help improve and simplify the code. The name of operator resolves the name of the variable passed into it.
Usage for your case would look like this:
public string ExampleFunction(string variableName) {
//Construct your log statement using c# 6.0 string interpolation
return $"Error occurred in {variableName}";
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(nameof(WhatIsMyName));
A major benefit is that it is done at compile time,
The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).
More information can be found here
Older Version Of C 3.0 and above
To Build on Nawfals answer
GetParameterName2(new { variable });
//Hack to assure compiler warning is generated specifying this method calling conventions
[Obsolete("Note you must use a single parametered AnonymousType When Calling this method")]
public static string GetParameterName<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
I know this post is really old, but since there is now a way in C#10 compiler, I thought I would share so others know.
You can now use CallerArgumentExpressionAttribute as shown
// Will throw argument exception if string IsNullOrEmpty returns true
public static void ValidateNotNullorEmpty(
this string str,
[CallerArgumentExpression("str")]string strName = null
)
{
if (string.IsNullOrEmpty(str))
{
throw new ArgumentException($"'{strName}' cannot be null or empty.", strName);
}
}
Now call with:
param.ValidateNotNullorEmpty();
will throw error: "param cannot be null or empty."
instead of "str cannot be null or empty"
static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}
static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
Enforce.That(properties.Length == 1);
return properties[0].Name;
}
More details are in this blog post.
Three ways:
1) Something without reflection at all:
GetParameterName1(new { variable });
public static string GetParameterName1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return item.ToString().TrimStart('{').TrimEnd('}').Split('=')[0].Trim();
}
2) Uses reflection, but this is way faster than other two.
GetParameterName2(new { variable });
public static string GetParameterName2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
3) The slowest of all, don't use.
GetParameterName3(() => variable);
public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
return ((MemberExpression)expr.Body).Member.Name;
}
To get a combo parameter name and value, you can extend these methods. Of course its easy to get value if you pass the parameter separately as another argument, but that's inelegant. Instead:
1)
public static string GetParameterInfo1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = item.ToString().TrimStart('{').TrimEnd('}').Split('=');
return "Parameter: '" + param[0].Trim() +
"' = " + param[1].Trim();
}
2)
public static string GetParameterInfo2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = typeof(T).GetProperties()[0];
return "Parameter: '" + param.Name +
"' = " + param.GetValue(item, null);
}
3)
public static string GetParameterInfo3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
var param = (MemberExpression)expr.Body;
return "Parameter: '" + param.Member.Name +
"' = " + ((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value);
}
1 and 2 are of comparable speed now, 3 is again sluggish.
Yes! It is possible. I have been looking for a solution to this for a long time and have finally come up with a hack that solves it (it's a bit nasty). I would not recommend using this as part of your program and I only think it works in debug mode. For me this doesn't matter as I only use it as a debugging tool in my console class so I can do:
int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);
the output to the console would be:
testVar: 1
testBoolVar: True
Here is the function I use to do that (not including the wrapping code for my console class.
public Dictionary<string, string> nameOfAlreadyAcessed = new Dictionary<string, string>();
public string nameOf(object obj, int level = 1)
{
StackFrame stackFrame = new StackTrace(true).GetFrame(level);
string fileName = stackFrame.GetFileName();
int lineNumber = stackFrame.GetFileLineNumber();
string uniqueId = fileName + lineNumber;
if (nameOfAlreadyAcessed.ContainsKey(uniqueId))
return nameOfAlreadyAcessed[uniqueId];
else
{
System.IO.StreamReader file = new System.IO.StreamReader(fileName);
for (int i = 0; i < lineNumber - 1; i++)
file.ReadLine();
string varName = file.ReadLine().Split(new char[] { '(', ')' })[1];
nameOfAlreadyAcessed.Add(uniqueId, varName);
return varName;
}
}
Continuing with the Caller* attribute series (i.e CallerMemberName, CallerFilePath and CallerLineNumber), CallerArgumentExpressionAttribute is available since C# Next (more info here).
The following example is inspired by Paul Mcilreavy's The CallerArgumentExpression Attribute in C# 8.0:
public static void ThrowIfNullOrWhitespace(this string self,
[CallerArgumentExpression("self")] string paramName = default)
{
if (self is null)
{
throw new ArgumentNullException(paramName);
}
if (string.IsNullOrWhiteSpace(self))
{
throw new ArgumentOutOfRangeException(paramName, self, "Value cannot be whitespace");
}
}
This would be very useful to do in order to create good exception messages causing people to be able to pinpoint errors better. Line numbers help, but you might not get them in prod, and when you do get them, if there are big statements in code, you typically only get the first line of the whole statement.
For instance, if you call .Value on a nullable that isn't set, you'll get an exception with a failure message, but as this functionality is lacking, you won't see what property was null. If you do this twice in one statement, for instance to set parameters to some method, you won't be able to see what nullable was not set.
Creating code like Verify.NotNull(myvar, nameof(myvar)) is the best workaround I've found so far, but would be great to get rid of the need to add the extra parameter.
No, but whenever you find yourself doing extremely complex things like this, you might want to re-think your solution. Remember that code should be easier to read than it was to write.
System.Environment.StackTrace will give you a string that includes the current call stack. You could parse that to get the information, which includes the variable names for each call.
Well Try this Utility class,
public static class Utility
{
public static Tuple<string, TSource> GetNameAndValue<TSource>(Expression<Func<TSource>> sourceExpression)
{
Tuple<String, TSource> result = null;
Type type = typeof (TSource);
Func<MemberExpression, Tuple<String, TSource>> process = delegate(MemberExpression memberExpression)
{
ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
var name = memberExpression.Member.Name;
var value = ((FieldInfo)memberExpression.Member).GetValue(constantExpression.Value);
return new Tuple<string, TSource>(name, (TSource) value);
};
Expression exception = sourceExpression.Body;
if (exception is MemberExpression)
{
result = process((MemberExpression)sourceExpression.Body);
}
else if (exception is UnaryExpression)
{
UnaryExpression unaryExpression = (UnaryExpression)sourceExpression.Body;
result = process((MemberExpression)unaryExpression.Operand);
}
else
{
throw new Exception("Expression type unknown.");
}
return result;
}
}
And User It Like
/*ToDo : Test Result*/
static void Main(string[] args)
{
/*Test : primivit types*/
long maxNumber = 123123;
Tuple<string, long> longVariable = Utility.GetNameAndValue(() => maxNumber);
string longVariableName = longVariable.Item1;
long longVariableValue = longVariable.Item2;
/*Test : user define types*/
Person aPerson = new Person() { Id = "123", Name = "Roy" };
Tuple<string, Person> personVariable = Utility.GetNameAndValue(() => aPerson);
string personVariableName = personVariable.Item1;
Person personVariableValue = personVariable.Item2;
/*Test : anonymous types*/
var ann = new { Id = "123", Name = "Roy" };
var annVariable = Utility.GetNameAndValue(() => ann);
string annVariableName = annVariable.Item1;
var annVariableValue = annVariable.Item2;
/*Test : Enum tyoes*/
Active isActive = Active.Yes;
Tuple<string, Active> isActiveVariable = Utility.GetNameAndValue(() => isActive);
string isActiveVariableName = isActiveVariable.Item1;
Active isActiveVariableValue = isActiveVariable.Item2;
}
Do this
var myVariable = 123;
myVariable.Named(() => myVariable);
var name = myVariable.Name();
// use name how you like
or naming in code by hand
var myVariable = 123.Named("my variable");
var name = myVariable.Name();
using this class
public static class ObjectInstanceExtensions
{
private static Dictionary<object, string> namedInstances = new Dictionary<object, string>();
public static void Named<T>(this T instance, Expression<Func<T>> expressionContainingOnlyYourInstance)
{
var name = ((MemberExpression)expressionContainingOnlyYourInstance.Body).Member.Name;
instance.Named(name);
}
public static T Named<T>(this T instance, string named)
{
if (namedInstances.ContainsKey(instance)) namedInstances[instance] = named;
else namedInstances.Add(instance, named);
return instance;
}
public static string Name<T>(this T instance)
{
if (namedInstances.ContainsKey(instance)) return namedInstances[instance];
throw new NotImplementedException("object has not been named");
}
}
Code tested and most elegant I can come up with.
Thanks for all the responses. I guess I'll just have to go with what I'm doing now.
For those who wanted to know why I asked the above question. I have the following function:
string sMessages(ArrayList aMessages, String sType) {
string sReturn = String.Empty;
if (aMessages.Count > 0) {
sReturn += "<p class=\"" + sType + "\">";
for (int i = 0; i < aMessages.Count; i++) {
sReturn += aMessages[i] + "<br />";
}
sReturn += "</p>";
}
return sReturn;
}
I send it an array of error messages and a css class which is then returned as a string for a webpage.
Every time I call this function, I have to define sType. Something like:
output += sMessages(aErrors, "errors");
As you can see, my variables is called aErrors and my css class is called errors. I was hoping my cold could figure out what class to use based on the variable name I sent it.
Again, thanks for all the responses.
thanks to visual studio 2022 , you can use this
function
public void showname(dynamic obj) {
obj.GetType().GetProperties().ToList().ForEach(state => {
NameAndValue($"{state.Name}:{state.GetValue(obj, null).ToString()}");
});
}
to use
var myname = "dddd";
showname(new { myname });
The short answer is no ... unless you are really really motivated.
The only way to do this would be via reflection and stack walking. You would have to get a stack frame, work out whereabouts in the calling function you where invoked from and then using the CodeDOM try to find the right part of the tree to see what the expression was.
For example, what if the invocation was ExampleFunction("a" + "b")?
No. A reference to your string variable gets passed to the funcion--there isn't any inherent metadeta about it included. Even reflection wouldn't get you out of the woods here--working backwards from a single reference type doesn't get you enough info to do what you need to do.
Better go back to the drawing board on this one!
rp
You could use reflection to get all the properties of an object, than loop through it, and get the value of the property where the name (of the property) matches the passed in parameter.
Well had a bit of look. of course you can't use any Type information.
Also, the name of a local variable is not available at runtime
because their names are not compiled into the assembly's metadata.
GateKiller, what's wrong with my workaround? You could rewrite your function trivially to use it (I've taken the liberty to improve the function on the fly):
static string sMessages(Expression<Func<List<string>>> aMessages) {
var messages = aMessages.Compile()();
if (messages.Count == 0) {
return "";
}
StringBuilder ret = new StringBuilder();
string sType = ((MemberExpression)aMessages.Body).Member.Name;
ret.AppendFormat("<p class=\"{0}\">", sType);
foreach (string msg in messages) {
ret.Append(msg);
ret.Append("<br />");
}
ret.Append("</p>");
return ret.ToString();
}
Call it like this:
var errors = new List<string>() { "Hi", "foo" };
var ret = sMessages(() => errors);
A way to get it can be reading the code file and splitting it with comma and parenthesis...
var trace = new StackTrace(true).GetFrame(1);
var line = File.ReadAllLines(trace.GetFileName())[trace.GetFileLineNumber()];
var argumentNames = line.Split(new[] { ",", "(", ")", ";" },
StringSplitOptions.TrimEntries)
.Where(x => x.Length > 0)
.Skip(1).ToList();
Extending on the accepted answer for this question, here is how you'd do it with #nullable enable source files:
internal static class StringExtensions
{
public static void ValidateNotNull(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (theString is null)
{
throw new ArgumentException($"'{theName}' cannot be null.", theName);
}
}
public static void ValidateNotNullOrEmpty(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrEmpty(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or empty.", theName);
}
}
public static void ValidateNotNullOrWhitespace(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrWhiteSpace(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or whitespace", theName);
}
}
}
What's nice about this code is that it uses [NotNull] attribute, so the static analysis will cooperate:
If I understand you correctly, you want the string "WhatIsMyName" to appear inside the Hello string.
string Hello = ExampleFunction(WhatIsMyName);
If the use case is that it increases the reusability of ExampleFunction and that Hello shall contain something like "Hello, Peter (from WhatIsMyName)", then I think a solution would be to expand the ExampleFunction to accept:
string Hello = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
So that the name is passed as a separate string. Yes, it is not exactly what you asked and you will have to type it twice. But it is refactor safe, readable, does not use the debug interface and the chance of Error is minimal because they appear together in the consuming code.
string Hello1 = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
string Hello2 = ExampleFunction(SomebodyElse,nameof(SomebodyElse));
string Hello3 = ExampleFunction(HerName,nameof(HerName));
No. I don't think so.
The variable name that you use is for your convenience and readability. The compiler doesn't need it & just chucks it out if I'm not mistaken.
If it helps, you could define a new class called NamedParameter with attributes Name and Param. You then pass this object around as parameters.

Get names of the params passed to a C# method

void MyMethod(string something, params object[] parameters)
{
foreach (object parameter in parameters)
{
// Get the name of each passed parameter
}
}
For example, if I call the method in the following way, I want to get the names "myFirstParam" and "anotherParam".
string myFirstParam = "some kind of text";
string anotherParam = 42;
MyMethod("test", myFirstParam, anotherParam);
Perhaps reflection is the answer? Perhaps it's just not possible? I am aware of the existance of this question, but that solution won't work here.
(Please do not respond with "This is not a good idea". That is not my question.)
This is totally impossible.
Here are just a few cases where it doesn't even make sense:
MyMethod("abc", new object[5]);
MyMethod("abc", "def");
MyMethod("abc", var1 + var2);
MyMethod("abc", SomeMethod());
MyMethod("abc", b ? a : c);
MyMethod("abc", new object());
MyMethod("abc", null);
In fact, local variable names aren't even compiled into the assembly.
Building on #shingo's answer.
Since C#10, you can get the name of the variable passed using CallerArgumentExpressionAttribute Class.
This is .NET6:
using System.Runtime.CompilerServices;
void F(object arg1, [CallerArgumentExpression("arg1")] string arg1Exp = "?")
=> Console.WriteLine($"{arg1Exp} => {arg1}");
var var1 = "C#10";
var var2 = "_";
var b = var1.Length > 7;
F(var1);
F(new object[5]);
F("def");
F(var1 + var2);
F(SomeMethod());
F(b ? var1 : var2);
F(new object());
F(null);
F(int.Parse(var1.Substring(2)) switch {
>= 10 => "Supported",
_ => "Not supported"
});
int SomeMethod() => 7 + 8;
Output (which seems magical):
var1 => C#10
new object[5] => System.Object[]
"def" => def
var1 + var2 => C#10_
SomeMethod() => 15
b ? var1 : var2 => _
new object() => System.Object
null =>
int.Parse(var1.Substring(2)) switch {
>= 10 => "Supported",
_ => "Not supported"
} => Supported
C# 10 has introduced a new attribute CallerArgumentExpressionAttribute.
Getting names from params parameters is still impossible, but if you have fixed number of parameters (like overload methods), then it's possible.
void MyMethod(object p0,
[CallerArgumentExpression("p0") string p0exp = "p0")
{
Console.WriteLine(p0exp);
}
void MyMethod(object p0, object p1,
[CallerArgumentExpression("p0") string p0exp = "p0",
[CallerArgumentExpression("p1") string p1exp = "p1")
{
}
In addition to SLaks's answer - variable names are not available at run-time at all. The variables are represented by stack slots and are addressed by an index. Thus you can't get this information even for the example you provided, not to mention all these examples SLaks provided. Reflection is no help here. Nothing is.
It is not possible, and I wonder why you would need that.
I RAISE THIS QUESTION FROM THE DEAD!
Check out C# 6.0's new nameof() operator. It allows you to do exactly what you want, and it actually isn't always a bad idea.
A good use case is Argument Exceptions, or INotifyPropertyChanged. (Especially when you get inheritance in the mix)
Example:
interface IFooBar
{
void Foo(object bar);
}
public class FooBar : IFooBar
{
public void Foo(object bar)
{
if(bar == null)
{
//Old and Busted
//throw new ArgumentException("bar");
//The new HOTNESS
throw new ArgumentException(nameof(bar)); // nameof(bar) returns "bar"
}
//....
}
}
Now, if you were rename the parameter 'bar' on the method 'Foo' in the interface IFooBar, your argument exceptions would update accordingly (prevents you from forgetting to change the "bar" string)
Pretty neat actually!
What about this;
void MyMethod(string something, object parameters)
{
RouteValueDictionary dic = HtmlHelper.AnonymousObjectToHtmlAttributes(options);
}
MyMethod("test", new { #myFirstParam=""some kind of text", anotherParam=42);
This has already been implemented in System.Web.MVC.Html InputExtension.
I was inspired and using this technique in my code.
It is very flexible.
Dont bother about "Html" naming in the helper methods. There is nothing to do with html, or html attributes inside the helper method.
It just converts named, anonymous arguments to RouteValueDictionary, a special dictionary having IDictionary<string,object> interface where key holds the argument name and object is the value of the argument.
Using reflection, and #Martin's example of null argument testing:
using System.Reflection;
public SomeMethod(ClassA a, ClassB b, ClassC c)
{
CheckNullParams(MethodBase.GetCurrentMethod(), a, b, c);
// do something here
}
accessing the parameter names:
public void CheckNullParams(MethodBase method, params object[] args)
{
for (var i=0; i < args.Count(); i++)
{
if (args[i] == null)
{
throw new ArgumentNullException(method.GetParameters()[i].Name);
}
}
}
This works with constructors and public methods, but I haven't tested beyond unit tests within VS, so possibly there are some runtime JIT issues (reading through articles referenced above).
EDIT: Just noticed, this is essentially the same as linked answer.

eval(string) to C# code

Is it possible to evaluate the following in C# at runtime
I have a class that contains 3 properties (Field,Operator,Value)
rule.Field;
rule.Operator;
rule.Value;
this is my rule class...
Now I have a loop
foreach(item in items)
{
// here I want to create a dynamic expression to evaluate at runtime
// something like
if (item.[rule.field] [rule.operator] [rule.value])
{ do work }
}
I just don't know the syntax, or if its possible in C#, I know in JS its possible but that's not a compiled language.
Update
Essentially I want a way to eval(stringCode) or a better more supported way.
No, C# doesn't support anything like this directly.
The closest options are:
Create a full valid C# program and dynamically compile it with CSharpCodeProvider.
Build an expression tree, compile and execute it
Perform the evaluation yourself (this may actually be easiest, depending on your operators etc)
Disclaimer: I'm the owner of the project Eval Expression.NET
This library is close to being the JS Eval equivalent. You can almost evaluate and compile all the C# language.
Here is a simple example using your question, but the library goes way beyond this simple scenario.
int field = 2;
int value = 1;
string binaryOperator = ">";
string formula = "x " + binaryOperator + " y";
// For single evaluation
var value1 = Eval.Execute<bool>(formula, new { x = field, y = value });
// For many evaluation
var compiled = Eval.Compile<Func<int, int, bool>>(formula, "x", "y");
var value2 = compiled(field, value);
EDIT Answer comment:
Proprietary library to do simple evaluation? No, thanks
This library does not support only simple evaluation but almost all the C# languages. Allowing you to add dynamically a method, use async, linq, loop, etc., which is more than "to do simple evaluation"
The closest options solution provided by Jon Skeet are great but will surely take several days of development and testing to support all cases, depending on the operators. Surely this library helps some developers, but in some other scenarios, like yours, it could be done without it.
I'm not entirely sure what you are saying. Can you try clarifying it a bit?
Are you wanting to to take a string expression and evaluate it at runtime in C#? If so the answer is no. C# does not support such types of dynamic evaluation.
You'd have to either use the CodeDOM libraries or create an Expression tree, compile it, and execute it. I think building up the expression tree is the best option.
Of course you could put in a switch statement on your operator, which is not bad because there is a limited number of operators you could use anyways.
Here's a way to do this with expression trees (written in LINQPad):
void Main()
{
var programmers = new List<Programmer>{
new Programmer { Name = "Turing", Number = Math.E},
new Programmer { Name = "Babbage", Number = Math.PI},
new Programmer { Name = "Lovelace", Number = Math.E}};
var rule0 = new Rule<string>() { Field = "Name", Operator = BinaryExpression.Equal, Value = "Turing" };
var rule1 = new Rule<double>() { Field = "Number", Operator = BinaryExpression.GreaterThan, Value = 2.719 };
var matched0 = RunRule<Programmer, string>(programmers, rule0);
matched0.Dump();
var matched1 = RunRule<Programmer, double>(programmers, rule1);
matched1.Dump();
var matchedBoth = matched0.Intersect(matched1);
matchedBoth.Dump();
var matchedEither = matched0.Union(matched1);
matchedEither.Dump();
}
public IEnumerable<T> RunRule<T, V>(IEnumerable<T> foos, Rule<V> rule) {
var fieldParam = Expression.Parameter(typeof(T), "f");
var fieldProp = Expression.Property (fieldParam, rule.Field);
var valueParam = Expression.Parameter(typeof(V), "v");
BinaryExpression binaryExpr = rule.Operator(fieldProp, valueParam);
var lambda = Expression.Lambda<Func<T, V, bool>>(binaryExpr, fieldParam, valueParam);
var func = lambda.Compile();
foreach(var foo in foos) {
var result = func(foo, rule.Value);
if(result)
yield return foo;
}
}
public class Rule<T> {
public string Field { get; set; }
public Func<Expression, Expression, BinaryExpression> Operator { get; set; }
public T Value { get; set; }
}
public class Programmer {
public string Name { get; set; }
public double Number { get; set; }
}
A better design for you would be for your rule to apply the test itself (or to an arbitrary value)
By doing this with Func instances you will get the most flexibility, like so:
IEnumerable<Func<T,bool> tests; // defined somehow at runtime
foreach (var item in items)
{
foreach (var test in tests)
{
if (test(item))
{
//do work with item
}
}
}
then your specific test would be something like this for strong type checking at compile time:
public Func<T,bool> FooEqualsX<T,V>(V x)
{
return t => EqualityComparer<V>.Default.Equals(t.Foo, x);
}
For a reflective form
public Func<T,bool> MakeTest<T,V>(string name, string op, V value)
{
Func<T,V> getter;
var f = typeof(T).GetField(name);
if (f != null)
{
if (!typeof(V).IsAssignableFrom(f.FieldType))
throw new ArgumentException(name +" incompatible with "+ typeof(V));
getter= x => (V)f.GetValue(x);
}
else
{
var p = typeof(T).GetProperty(name);
if (p == null)
throw new ArgumentException("No "+ name +" on "+ typeof(T));
if (!typeof(V).IsAssignableFrom(p.PropertyType))
throw new ArgumentException(name +" incompatible with "+ typeof(V));
getter= x => (V)p.GetValue(x, null);
}
switch (op)
{
case "==":
return t => EqualityComparer<V>.Default.Equals(getter(t), value);
case "!=":
return t => !EqualityComparer<V>.Default.Equals(getter(t), value);
case ">":
return t => Comparer<V>.Default.Compare(getter(t), value) > 0;
// fill in the banks as you need to
default:
throw new ArgumentException("unrecognised operator '"+ op +"'");
}
}
If you wanted to be really introspective and handle any literal without knowing at compile time you could use the CSharpCodeProvider to compile a function assuming something like:
public static bool Check(T t)
{
// your code inserted here
}
This is of course a massive security hole so whoever can supply code for this must be fully trusted. Here is a somewhat limited implementation for your specific needs (no sanity checking at all)
private Func<T,bool> Make<T>(string name, string op, string value)
{
var foo = new Microsoft.CSharp.CSharpCodeProvider()
.CompileAssemblyFromSource(
new CompilerParameters(),
new[] { "public class Foo { public static bool Eval("+
typeof(T).FullName +" t) { return t."+
name +" "+ op +" "+ value
+"; } }" }).CompiledAssembly.GetType("Foo");
return t => (bool)foo.InvokeMember("Eval",
BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod ,
null, null, new object[] { t });
}
// use like so:
var f = Make<string>("Length", ">", "2");
For this to work with arbitrary types you would have to do a bit more reflection to find the target assembly for the type to reference it in the compiler parameters.
private bool Eval(object item, string name, string op, string value)
{
var foo = new Microsoft.CSharp.CSharpCodeProvider()
.CompileAssemblyFromSource(
new CompilerParameters(),
new[] { "public class Foo { public static bool Eval("+
item.GetType().FullName +" t) "+
"{ return t."+ name +" "+ op +" "+ value +"; } }"
}).CompiledAssembly.GetType("Foo");
return (bool)foo.InvokeMember("Eval",
BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod ,
null, null, new object[] { item });
}
All the above code is simply a proof of concept, it lacks sanity checking and has serious performance issues.
If you wanted to be even fancier you could use Reflection.Emit with DynamicMethod instances to do it (using proper operators rather than the default comparer instances) but this would require complex handling for types with overridden operators.
By making your check code highly generic you may include more tests in future as you need to. Essentially isolate the part of your code that cares only about a function from t -> true/false from the code that supplies these functions.
CSharpCodeProvider; switch statements that pick the proper different "operators"; the DLR... they are all ways you could do this; but they seem weird solutions to me.
How about just using delegates?
Assuming your Field and Value are numbers, declare something like this:
delegate bool MyOperationDelegate(decimal left, decimal right);
...
class Rule {
decimal Field;
decimal Value;
MyOperationDelegate Operator;
}
Now you can define your 'rule' as, for example, a bunch of lambdas:
Rule rule1 = new Rule;
rule1.Operation = (decimal l, decimal r) => { return l > r; };
rule1.Field = ...
You can make arrays of rules and apply them whichever way you wish.
IEnumerable<Rule> items = ...;
foreach(item in items)
{
if (item.Operator(item.Field, item.Value))
{ /* do work */ }
}
If Field and Values are not numbers, or the type depends on the specific rule, you can use object instead of decimal, and with a little bit of casting you can make it all work.
That's not a final design; it's just to give you some ideas (for example, you would likely have the class evaluate the delegate on its own via a Check() method or something).
You can retrieve the field by reflection. And then implement the operators as methods and uses reflection or some types of enum-delegate mapping to call the operators. The operators should have at least 2 parameters, the input value and the value you are using to test against with.
While it is true that you probably won't find an elegant way to evaluate full C# code on the fly without the use of dynamically compiling code (which is never pretty), you can almost certainly get your rules evaluated in short order using either the DLR (IronPython, IronRuby, etc) or an expression evaluator library that parses and executes a custom syntax. There is one, Script.NET, that provides a very similar syntax to C#.
Take a look here:Evaluating Expressions a Runtime in .NET(C#)
If you have the time / inclination to learn a little Python, then IronPython and the DLR will solve all your issues:
Extending your App with IronPython

How can I get the name of a variable passed into a function?

Let me use the following example to explain my question:
public string ExampleFunction(string Variable) {
return something;
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(WhatIsMyName);
When I pass the variable WhatIsMyName to the ExampleFunction, I want to be able to get a string of the original variable's name. Perhaps something like:
Variable.OriginalName.ToString() // == "WhatIsMyName"
Is there any way to do this?
What you want isn't possible directly but you can use Expressions in C# 3.0:
public void ExampleFunction(Expression<Func<string, string>> f) {
Console.WriteLine((f.Body as MemberExpression).Member.Name);
}
ExampleFunction(x => WhatIsMyName);
Note that this relies on unspecified behaviour and while it does work in Microsoft’s current C# and VB compilers, and in Mono’s C# compiler, there’s no guarantee that this won’t stop working in future versions.
This isn't exactly possible, the way you would want. C# 6.0 they Introduce the nameof Operator which should help improve and simplify the code. The name of operator resolves the name of the variable passed into it.
Usage for your case would look like this:
public string ExampleFunction(string variableName) {
//Construct your log statement using c# 6.0 string interpolation
return $"Error occurred in {variableName}";
}
string WhatIsMyName = "Hello World";
string Hello = ExampleFunction(nameof(WhatIsMyName));
A major benefit is that it is done at compile time,
The nameof expression is a constant. In all cases, nameof(...) is evaluated at compile-time to produce a string. Its argument is not evaluated at runtime, and is considered unreachable code (however it does not emit an "unreachable code" warning).
More information can be found here
Older Version Of C 3.0 and above
To Build on Nawfals answer
GetParameterName2(new { variable });
//Hack to assure compiler warning is generated specifying this method calling conventions
[Obsolete("Note you must use a single parametered AnonymousType When Calling this method")]
public static string GetParameterName<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
I know this post is really old, but since there is now a way in C#10 compiler, I thought I would share so others know.
You can now use CallerArgumentExpressionAttribute as shown
// Will throw argument exception if string IsNullOrEmpty returns true
public static void ValidateNotNullorEmpty(
this string str,
[CallerArgumentExpression("str")]string strName = null
)
{
if (string.IsNullOrEmpty(str))
{
throw new ArgumentException($"'{strName}' cannot be null or empty.", strName);
}
}
Now call with:
param.ValidateNotNullorEmpty();
will throw error: "param cannot be null or empty."
instead of "str cannot be null or empty"
static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}
static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
Enforce.That(properties.Length == 1);
return properties[0].Name;
}
More details are in this blog post.
Three ways:
1) Something without reflection at all:
GetParameterName1(new { variable });
public static string GetParameterName1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return item.ToString().TrimStart('{').TrimEnd('}').Split('=')[0].Trim();
}
2) Uses reflection, but this is way faster than other two.
GetParameterName2(new { variable });
public static string GetParameterName2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
3) The slowest of all, don't use.
GetParameterName3(() => variable);
public static string GetParameterName3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
return ((MemberExpression)expr.Body).Member.Name;
}
To get a combo parameter name and value, you can extend these methods. Of course its easy to get value if you pass the parameter separately as another argument, but that's inelegant. Instead:
1)
public static string GetParameterInfo1<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = item.ToString().TrimStart('{').TrimEnd('}').Split('=');
return "Parameter: '" + param[0].Trim() +
"' = " + param[1].Trim();
}
2)
public static string GetParameterInfo2<T>(T item) where T : class
{
if (item == null)
return string.Empty;
var param = typeof(T).GetProperties()[0];
return "Parameter: '" + param.Name +
"' = " + param.GetValue(item, null);
}
3)
public static string GetParameterInfo3<T>(Expression<Func<T>> expr)
{
if (expr == null)
return string.Empty;
var param = (MemberExpression)expr.Body;
return "Parameter: '" + param.Member.Name +
"' = " + ((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value);
}
1 and 2 are of comparable speed now, 3 is again sluggish.
Yes! It is possible. I have been looking for a solution to this for a long time and have finally come up with a hack that solves it (it's a bit nasty). I would not recommend using this as part of your program and I only think it works in debug mode. For me this doesn't matter as I only use it as a debugging tool in my console class so I can do:
int testVar = 1;
bool testBoolVar = True;
myConsole.Writeline(testVar);
myConsole.Writeline(testBoolVar);
the output to the console would be:
testVar: 1
testBoolVar: True
Here is the function I use to do that (not including the wrapping code for my console class.
public Dictionary<string, string> nameOfAlreadyAcessed = new Dictionary<string, string>();
public string nameOf(object obj, int level = 1)
{
StackFrame stackFrame = new StackTrace(true).GetFrame(level);
string fileName = stackFrame.GetFileName();
int lineNumber = stackFrame.GetFileLineNumber();
string uniqueId = fileName + lineNumber;
if (nameOfAlreadyAcessed.ContainsKey(uniqueId))
return nameOfAlreadyAcessed[uniqueId];
else
{
System.IO.StreamReader file = new System.IO.StreamReader(fileName);
for (int i = 0; i < lineNumber - 1; i++)
file.ReadLine();
string varName = file.ReadLine().Split(new char[] { '(', ')' })[1];
nameOfAlreadyAcessed.Add(uniqueId, varName);
return varName;
}
}
Continuing with the Caller* attribute series (i.e CallerMemberName, CallerFilePath and CallerLineNumber), CallerArgumentExpressionAttribute is available since C# Next (more info here).
The following example is inspired by Paul Mcilreavy's The CallerArgumentExpression Attribute in C# 8.0:
public static void ThrowIfNullOrWhitespace(this string self,
[CallerArgumentExpression("self")] string paramName = default)
{
if (self is null)
{
throw new ArgumentNullException(paramName);
}
if (string.IsNullOrWhiteSpace(self))
{
throw new ArgumentOutOfRangeException(paramName, self, "Value cannot be whitespace");
}
}
This would be very useful to do in order to create good exception messages causing people to be able to pinpoint errors better. Line numbers help, but you might not get them in prod, and when you do get them, if there are big statements in code, you typically only get the first line of the whole statement.
For instance, if you call .Value on a nullable that isn't set, you'll get an exception with a failure message, but as this functionality is lacking, you won't see what property was null. If you do this twice in one statement, for instance to set parameters to some method, you won't be able to see what nullable was not set.
Creating code like Verify.NotNull(myvar, nameof(myvar)) is the best workaround I've found so far, but would be great to get rid of the need to add the extra parameter.
No, but whenever you find yourself doing extremely complex things like this, you might want to re-think your solution. Remember that code should be easier to read than it was to write.
System.Environment.StackTrace will give you a string that includes the current call stack. You could parse that to get the information, which includes the variable names for each call.
Well Try this Utility class,
public static class Utility
{
public static Tuple<string, TSource> GetNameAndValue<TSource>(Expression<Func<TSource>> sourceExpression)
{
Tuple<String, TSource> result = null;
Type type = typeof (TSource);
Func<MemberExpression, Tuple<String, TSource>> process = delegate(MemberExpression memberExpression)
{
ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
var name = memberExpression.Member.Name;
var value = ((FieldInfo)memberExpression.Member).GetValue(constantExpression.Value);
return new Tuple<string, TSource>(name, (TSource) value);
};
Expression exception = sourceExpression.Body;
if (exception is MemberExpression)
{
result = process((MemberExpression)sourceExpression.Body);
}
else if (exception is UnaryExpression)
{
UnaryExpression unaryExpression = (UnaryExpression)sourceExpression.Body;
result = process((MemberExpression)unaryExpression.Operand);
}
else
{
throw new Exception("Expression type unknown.");
}
return result;
}
}
And User It Like
/*ToDo : Test Result*/
static void Main(string[] args)
{
/*Test : primivit types*/
long maxNumber = 123123;
Tuple<string, long> longVariable = Utility.GetNameAndValue(() => maxNumber);
string longVariableName = longVariable.Item1;
long longVariableValue = longVariable.Item2;
/*Test : user define types*/
Person aPerson = new Person() { Id = "123", Name = "Roy" };
Tuple<string, Person> personVariable = Utility.GetNameAndValue(() => aPerson);
string personVariableName = personVariable.Item1;
Person personVariableValue = personVariable.Item2;
/*Test : anonymous types*/
var ann = new { Id = "123", Name = "Roy" };
var annVariable = Utility.GetNameAndValue(() => ann);
string annVariableName = annVariable.Item1;
var annVariableValue = annVariable.Item2;
/*Test : Enum tyoes*/
Active isActive = Active.Yes;
Tuple<string, Active> isActiveVariable = Utility.GetNameAndValue(() => isActive);
string isActiveVariableName = isActiveVariable.Item1;
Active isActiveVariableValue = isActiveVariable.Item2;
}
Do this
var myVariable = 123;
myVariable.Named(() => myVariable);
var name = myVariable.Name();
// use name how you like
or naming in code by hand
var myVariable = 123.Named("my variable");
var name = myVariable.Name();
using this class
public static class ObjectInstanceExtensions
{
private static Dictionary<object, string> namedInstances = new Dictionary<object, string>();
public static void Named<T>(this T instance, Expression<Func<T>> expressionContainingOnlyYourInstance)
{
var name = ((MemberExpression)expressionContainingOnlyYourInstance.Body).Member.Name;
instance.Named(name);
}
public static T Named<T>(this T instance, string named)
{
if (namedInstances.ContainsKey(instance)) namedInstances[instance] = named;
else namedInstances.Add(instance, named);
return instance;
}
public static string Name<T>(this T instance)
{
if (namedInstances.ContainsKey(instance)) return namedInstances[instance];
throw new NotImplementedException("object has not been named");
}
}
Code tested and most elegant I can come up with.
Thanks for all the responses. I guess I'll just have to go with what I'm doing now.
For those who wanted to know why I asked the above question. I have the following function:
string sMessages(ArrayList aMessages, String sType) {
string sReturn = String.Empty;
if (aMessages.Count > 0) {
sReturn += "<p class=\"" + sType + "\">";
for (int i = 0; i < aMessages.Count; i++) {
sReturn += aMessages[i] + "<br />";
}
sReturn += "</p>";
}
return sReturn;
}
I send it an array of error messages and a css class which is then returned as a string for a webpage.
Every time I call this function, I have to define sType. Something like:
output += sMessages(aErrors, "errors");
As you can see, my variables is called aErrors and my css class is called errors. I was hoping my cold could figure out what class to use based on the variable name I sent it.
Again, thanks for all the responses.
thanks to visual studio 2022 , you can use this
function
public void showname(dynamic obj) {
obj.GetType().GetProperties().ToList().ForEach(state => {
NameAndValue($"{state.Name}:{state.GetValue(obj, null).ToString()}");
});
}
to use
var myname = "dddd";
showname(new { myname });
The short answer is no ... unless you are really really motivated.
The only way to do this would be via reflection and stack walking. You would have to get a stack frame, work out whereabouts in the calling function you where invoked from and then using the CodeDOM try to find the right part of the tree to see what the expression was.
For example, what if the invocation was ExampleFunction("a" + "b")?
No. A reference to your string variable gets passed to the funcion--there isn't any inherent metadeta about it included. Even reflection wouldn't get you out of the woods here--working backwards from a single reference type doesn't get you enough info to do what you need to do.
Better go back to the drawing board on this one!
rp
You could use reflection to get all the properties of an object, than loop through it, and get the value of the property where the name (of the property) matches the passed in parameter.
Well had a bit of look. of course you can't use any Type information.
Also, the name of a local variable is not available at runtime
because their names are not compiled into the assembly's metadata.
GateKiller, what's wrong with my workaround? You could rewrite your function trivially to use it (I've taken the liberty to improve the function on the fly):
static string sMessages(Expression<Func<List<string>>> aMessages) {
var messages = aMessages.Compile()();
if (messages.Count == 0) {
return "";
}
StringBuilder ret = new StringBuilder();
string sType = ((MemberExpression)aMessages.Body).Member.Name;
ret.AppendFormat("<p class=\"{0}\">", sType);
foreach (string msg in messages) {
ret.Append(msg);
ret.Append("<br />");
}
ret.Append("</p>");
return ret.ToString();
}
Call it like this:
var errors = new List<string>() { "Hi", "foo" };
var ret = sMessages(() => errors);
A way to get it can be reading the code file and splitting it with comma and parenthesis...
var trace = new StackTrace(true).GetFrame(1);
var line = File.ReadAllLines(trace.GetFileName())[trace.GetFileLineNumber()];
var argumentNames = line.Split(new[] { ",", "(", ")", ";" },
StringSplitOptions.TrimEntries)
.Where(x => x.Length > 0)
.Skip(1).ToList();
Extending on the accepted answer for this question, here is how you'd do it with #nullable enable source files:
internal static class StringExtensions
{
public static void ValidateNotNull(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (theString is null)
{
throw new ArgumentException($"'{theName}' cannot be null.", theName);
}
}
public static void ValidateNotNullOrEmpty(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrEmpty(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or empty.", theName);
}
}
public static void ValidateNotNullOrWhitespace(
[NotNull] this string? theString,
[CallerArgumentExpression("theString")] string? theName = default)
{
if (string.IsNullOrWhiteSpace(theString))
{
throw new ArgumentException($"'{theName}' cannot be null or whitespace", theName);
}
}
}
What's nice about this code is that it uses [NotNull] attribute, so the static analysis will cooperate:
If I understand you correctly, you want the string "WhatIsMyName" to appear inside the Hello string.
string Hello = ExampleFunction(WhatIsMyName);
If the use case is that it increases the reusability of ExampleFunction and that Hello shall contain something like "Hello, Peter (from WhatIsMyName)", then I think a solution would be to expand the ExampleFunction to accept:
string Hello = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
So that the name is passed as a separate string. Yes, it is not exactly what you asked and you will have to type it twice. But it is refactor safe, readable, does not use the debug interface and the chance of Error is minimal because they appear together in the consuming code.
string Hello1 = ExampleFunction(WhatIsMyName,nameof(WhatIsMyName));
string Hello2 = ExampleFunction(SomebodyElse,nameof(SomebodyElse));
string Hello3 = ExampleFunction(HerName,nameof(HerName));
No. I don't think so.
The variable name that you use is for your convenience and readability. The compiler doesn't need it & just chucks it out if I'm not mistaken.
If it helps, you could define a new class called NamedParameter with attributes Name and Param. You then pass this object around as parameters.

Categories