tags:

views:

934

answers:

7
+6  Q: 

C# Eval() support

Hi Guys,
we need to evaluate a value in an object in run time while we have a textual statement of the exact member path for example: myobject.firstMember.secondMember[3].text
we thought of parsing this textual statement using regex and then evaluate the text value by using reflection but before we do that i wonder if C# support some kind of eval ability? so we won't have to do the parsing ourself. How do microsoft do this in their immediate window or watch windows?

thanks you very much,

Adi Barda

+1  A: 

AFAIK there is no such built-in Eval function. You'll have to go the Regex+Reflection way. I also think that Visual Studio is doing the same.

Vilx-
+5  A: 

In the future (around the 5.0 timeframe), the "compiler as a service" may be able to do this. Actually, you may be able to do a lot of this now with "mono" (see CsharpRepl and Mono.CSharp - however, I expect it'll need to know a lot more about the context to be able to use local variables etc in Evaluate) - but there isn't any support for this in the current MS .NET offering.

For now, you would have to do something like what a lot of the data-binding code does... split it apart by tokens such as "." and use reflection. Strictly speaking, the binding code actually uses TypeDescriptor/PropertyDescriptor rather than direct reflection, but the effect is the same.

Marc Gravell
+1  A: 

Although a somewhat heavy-weight approach, you can use C# CodeDom to emit a new a new assembly that contains a method with just that line of code.

This is much more heavy-handed than some of the other suggestions, I admit, but on the other hand you let the C# parser do the heavy lifting, so it should be able to handle everything you throw at it as long as it's valid C#.

If you go that route, you also need to ensure that you can unload the emitted assembly again, so creating and unloading AppDomains may be necessary.

I have successfully implemented and used the above technique. On the other hand, if you can use a DynamicMethod it would be much more light-weight. However, I have never tried that approach, so I can't say whether you can implement a DynamicMethod's body using C# literals.

Mark Seemann
A: 

Here's something similar I'm using to find dynamically nested properties.. you'd need to addthe logic for indexers... and some extra checking... i'm catching nulls/errors in my calling method...

  public static object FindDottedProperty(this object input, string propertyName)
  {
    if (input == null)
      return null;

    if (string.IsNullOrEmpty(propertyName))
      return null;

    Queue props = new Queue(propertyName.Split('.'));
    if (props.Count == 0) return null;

    //start with input object and roll out property stack from there.
    object ret = input;
    while (props.Count > 0)
    {
      var prop = props.Dequeue();
      if (string.IsNullOrEmpty(prop)) return null;

      /*** ADD INDEXER LOGIC HERE ***/

      //get the property's value based on the current named item
      ret = ret.GetType().GetProperty(prop).GetValue(ret, null);

      if (null.Equals(ret)) return null;
    }

    //return looked up value
    return ret;
  }
Tracker1
+1  A: 

Actually, the expression evaluation and rules engine feature of Windows Workflow Foundation can do things like this. See Introduction to the Windows Workflow Foundation Rules Engine.

One interesting thing about these components is that they were designed so that you can host the design-time components in your own applications to design sets of rules and/or expressions that operate in the context of your own custom classes. For instance, you'd tell it to design an expression against "myObject", and it would know that there's a firstMember which has a secondMember which has an indexer yielding a type that has a text property. You can persist the expressions and rules as XML, and read them back at runtime, without needing to use the designer at runtime.

In particular, see External RuleSet Toolkit Sample.

John Saunders
+3  A: 

Probably the easies way is to use DataBinder.Eval from System.Web.UI:

var foo = new Foo() { Bar = new Bar() { Value = "Value" } };
var value = DataBinder.Eval(foo, "Bar.Value");
Alex Yakunin
A: 

You can always try my light-weight C# Eval program. It compiles a substantial subset of the C# language to dynamic methods. Full details on my website KamimuCode.Com

David Wynne