Specifying the class name in the new clause in dynamic LINQ

c# dynamic-linq


What modifications are necessary for Dynamic LINQ to have the specified class's fields?

How, for instance, can the following C# query be translated into DLinq:

var carsPartial = cars.Select(c => new {c.year, c.name, make = new maker() {name = c.make.name} }).ToList();

To enable the return type to be the caller type rather than an anonymous type, I have implemented the adjustments indicated in this response https://stackoverflow.com/a/1468357/288747.

If it's any assistance, the class definition is as follows:

class car
    public int vid;
    public int odo;
    public int year;

    public string name;

    public maker make;

class maker
    public string name;
    public int firstYear;

The following does not function (while I believe it comes close, it still does not because I need the modifications to the dynamic linq library that are required), which is what I need:

var carsPartial = cars.Select("new(name, year, new maker() {name = make.name})").ToList();

However, it fails at thenew maker() { (As anticipated).

I'm certain that I need to modifyDynamicLibrary.cs to make this work and might need some guidance on how to modify it to do this.

5/23/2017 12:29:37 PM

Accepted Answer

Zzz-3-ZZZ: My response has evolved into a little longer zzz-8-ZZZ.

Although I don't think I've ever used the Dynamic Linq library, I did look at the DynamicLibrary.cs code and saw the modification to allow creating type classes that was made in another ask on stackoverflow that you linked to in your query. Upon further examination, it seems that the nestednew In your arrangement, -s ought to operate right out of the box.

However, it seems that the language query you submitted for Dynamic Linq is incorrect. Be aware that the query string for DLinq has its own syntax and is equal to C# at is not.

I think the question should be interpreted as follows:

var carsPartial = cars.Select("new(name, year, new maker(make.name as name) as make)").ToList();


After giving this question from stackoverflow another look, I see that it really does not provide the ability to create new strong-typed classes to the Dynamic Linq language. They just applied the outcome to the class specified as a generic parameter.Select() rather to include it in the query string.

You must undo their modifications (use generic DLinq) and implement my changes, which I have recently confirmed to work, in order to achieve what you need:

Discover theParseNew manner ofExpressionParser class and alter it to read as follows:

    Expression ParseNew() {

        bool anonymous = true;
        Type class_type = null;

        if (token.id == TokenId.Identifier)
            anonymous = false;
            StringBuilder full_type_name = new StringBuilder(GetIdentifier());


            while (token.id == TokenId.Dot)
                ValidateToken(TokenId.Identifier, Res.IdentifierExpected);

            class_type = Type.GetType(full_type_name.ToString(), false);    
            if (class_type == null)
                throw ParseError(Res.TypeNotFound, full_type_name.ToString());

        ValidateToken(TokenId.OpenParen, Res.OpenParenExpected);
        List<DynamicProperty> properties = new List<DynamicProperty>();
        List<Expression> expressions = new List<Expression>();
        while (true) {
            int exprPos = token.pos;
            Expression expr = ParseExpression();
            string propName;
            if (TokenIdentifierIs("as")) {
                propName = GetIdentifier();
            else {
                MemberExpression me = expr as MemberExpression;
                if (me == null) throw ParseError(exprPos, Res.MissingAsClause);
                propName = me.Member.Name;
            properties.Add(new DynamicProperty(propName, expr.Type));
            if (token.id != TokenId.Comma) break;
        ValidateToken(TokenId.CloseParen, Res.CloseParenOrCommaExpected);
        Type type = anonymous ? DynamicExpression.CreateClass(properties) : class_type; 
        MemberBinding[] bindings = new MemberBinding[properties.Count];
        for (int i = 0; i < bindings.Length; i++)
            bindings[i] = Expression.Bind(type.GetProperty(properties[i].Name), expressions[i]);
        return Expression.MemberInit(Expression.New(type), bindings);

then locate the class.Res add the following error message:

public const string TypeNotFound = "Type {0} not found";

Et voilĂ , you can create queries like these:

var carsPartial = cars.Select("new(name, year, (new your_namespace.maker(make.name as name)) as make)").ToList();

Be careful to supply the whole type name, which includes the entire namespace and class path.

It just determines if there is an identifier between to clarify my change.new closing parenthesis (see the added "if" at the begging). If so, we attempt to determine the whole dot-separated class name by parsing it.Type through Type.GetType instead of creating a new class when dealing with anonymousnew s.

5/23/2017 12:06:39 PM

Popular Answer

If I've got it right, you want to create a simple anonymous class with fields from both.class car and class maker . If such is the case, you may simply give that class new names, such as these:

var carsPartial = cars.Select(c => new { year = c.year, name = c.name, make_name = c.make.name });

Or maybe just provide names to fields that conflict:

var carsPartial = cars.Select(c => new { c.year, c.name, make_name = c.make.name });

Related Questions

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow