Question

I have a string stored in my db:

"Users.ElementAt(1).LastName"

I then have an object like so:

        MyClass myclass = new MyClass ()
        {
            Users = new List<User>()
            {
                new User()
                {
                    LastName = "LastName1"
                },
                new User()
                {
                    LastName = "LastName2"
                },
            }
        };  

Is there a way to either parse/evaluate/run the given string against my object to get each users last name?

I've been using the DynamicLinq library, but I am running into an issue with ElementAt(1) with the error message:

"No applicable aggregate method 'ElementAt' exists"

Can anyone provide some guidance here? Will I have to resort to writing my own parser and using reflection?

Was it helpful?

Solution

It looks like DynamicLinq's expression parser only supports a subset of the standard LINQ operator methods:

interface IEnumerableSignatures
{
    void Where(bool predicate);
    void Any();
    void Any(bool predicate);
    void All(bool predicate);
    void Count();
    void Count(bool predicate);
    void Min(object selector);
    void Max(object selector);
    void Sum(int selector);
    void Sum(int? selector);
    void Sum(long selector);
    void Sum(long? selector);
    void Sum(float selector);
    void Sum(float? selector);
    void Sum(double selector);
    void Sum(double? selector);
    void Sum(decimal selector);
    void Sum(decimal? selector);
    void Average(int selector);
    void Average(int? selector);
    void Average(long selector);
    void Average(long? selector);
    void Average(float selector);
    void Average(float? selector);
    void Average(double selector);
    void Average(double? selector);
    void Average(decimal selector);
    void Average(decimal? selector);
    void Take(int count);
    void Union(IQueryable right);
    void OrderBy(LambdaExpression exp);
    void OrderByDescending(LambdaExpression exp);
}

As you can see, ElementAt is not among them. The good news is that simply adding void ElementAt(int index); to IEnumerableSignatures appears to work just fine. That is, of course, assuming the LINQ query provider you are using will handle the ElementAt operator; it is entirely possible that it will not.

But if modifying the DynamicLinq source isn't an option, then no, there are no facilities within the core .NET Framework or LINQ which will parse and evaluate those kinds of expressions. There are other options (see ScriptCS, Roslyn), but I suspect you are drifting towards an "overkill" solution to whatever actual problem you are trying to solve.

OTHER TIPS

var allLastNamesInList= Users.Select(x=> x.LastName).toList();

This statement will iterate through the list and get all last names. You can even use order by as well so that you will get last names in order.

Is this is the requirement you are looking for or something different ?

I am not certain if you really need dynamic linq to do what you want. Just regular System.Linq should handle finding indexes of position and also the element at should work just fine if you are using C# .NET 4.5 or 4.0 in my experience. Here is a simple console app that should work fine:

using System;
using System.Collections.Generic;
using System.Linq;


public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}


class Program
{
    public static List<User> Users;

    static void Main(string[] args)
    {
            Users = new List<User>
            {
                new User
                    {
                        FirstName = "Brett",
                        LastName = "M"
                    },
                new User
                    {
                        FirstName = "John",
                        LastName = "Doe"
                    },
            new User
                {
                    FirstName = "Sam",
                    LastName = "Dilat"
                }
            };

        Console.WriteLine("Should work as long as object is defined and instantiated");
        Console.WriteLine(Users.ElementAt(1).FirstName);


        Console.WriteLine("\nIterate Through List with Linq\n I use a string you can add to another list or whatever\n\n");

        string s = "";

        Users.ForEach(n => s += "Position: " + Users.IndexOf(n) + " " + n.LastName + Environment.NewLine);
        Console.WriteLine(s);

        Console.ReadLine();
    }

}

And if you just want to find a particular Object in a collection by a property of that collection you can use the 'FindIndex' method:

Console.WriteLine("Index of Dilat: " + Users.FindIndex(n => n.LastName.Equals("Dilat")));

EDIT 9-27-13 for string to split.

If you want to take a string and split it up into a nice enurable list to iterate through you can do that too. You merely need to find the seperator. If you do not have one you are going to have to use some regex magic which is more complicated.

Keep everything the same but substituting my MAIN method:

string split = "Brett,Same,John,Frank";

        List<string> stringList = split.Split(',').ToList();

        string s = "";

        stringList.ForEach(n => s += n + Environment.NewLine);

        s += "\n\nFor Observing Element at\n";

        s += "John is at: " + stringList.FindIndex(n => n.Equals("John"));

        s += "\n\nGetting Poco Objects assigned and listed\n";

        var list = stringList.Select(u => new User
            {
                FirstName = u,
                LastName = "Something"
            }).ToList();

        list.ForEach(n => s += "User: " + n.FirstName + " " + n.LastName + "At: " + list.IndexOf(n) + Environment.NewLine);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top