Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Cast/As for non enumerable properties #566

Closed
dsidedp opened this issue Feb 9, 2022 · 9 comments
Closed

Support Cast/As for non enumerable properties #566

dsidedp opened this issue Feb 9, 2022 · 9 comments
Assignees
Labels

Comments

@dsidedp
Copy link

dsidedp commented Feb 9, 2022

Consider the following

    public class BaseClass {}

    public class DerivedClass1 
    {
        public int DerivedProperty1 { get; set; }
    }

    public class DerivedClass2
    {
        public int DerivedProperty2 { get; set; }
    }

    public class SomeClass
    {
        public BaseClass Item { get; set; }
    }

As far as I understand, currently, it is not possible to filter List<SomeClass> based on SomeClass.Item derived class property value since there is no way to cast non-enumerable property SomeClass.Item to DerivedClass1 or DerivedClass2:

Please consider supporting Cast/As/Is for non-enumerable properties.

    var list = new List<SomeClass>(){.....};
    //cast function
    var result1 = list.Where("Cast(Item, DerivedClass1).DerivedProperty1 == str")
    //this should correspond to 
     var linq1 = list.Where(x=> ((DerivedClass1)x.Item).DerivedProperty1 == str)

    //as/is as operators or functions
    var result2 = list.Where("(Item as DerivedClass1).DerivedProperty1 == str")
    var result3 = list.Where("As(Item, DerivedClass1).DerivedProperty1 == str")
    var linq2 = list.Where(x=> (x.Item as DerivedClass1).DerivedProperty1 == str)

result1 and corresponding linq1 cases are very useful when parsed expression is passed to EF or other ORMs with inheritance support.

Thanks.

@StefH
Copy link
Collaborator

StefH commented Feb 15, 2022

@StefH StefH added the question label Feb 15, 2022
@StefH StefH self-assigned this Feb 15, 2022
@dsidedp
Copy link
Author

dsidedp commented Feb 15, 2022

OfType is applicable to enumerables only. As is applied to It but not to It.Property.

Maybe I miss something, but I was not able to cast property of it when property is not Enumerable.

@StefH
Copy link
Collaborator

StefH commented Feb 16, 2022

@StefH StefH closed this as completed Feb 16, 2022
@dsidedp
Copy link
Author

dsidedp commented Feb 16, 2022

This is not the case.

In example you referred to, cast is applied to it to get access to it.DerivedProperty. And I'm talking about casting it.Property to get access to it.Property.DerivedProperty.

If it.Property is Enumerable, then OfType can be used. But there are no options if it.Property is an object.
Take a look at pseudo-code example provided in the first comment.

BTW, here is the similar issue #519

Here is the simple test for this case

    public void Test1()
    {
        // Assign
        var qry = new[]
        {
            new { Employee = (BaseEmployee)new Worker { Name = "1", Other = "x" }},
            new { Employee = (BaseEmployee)new Boss { Name = "2", Function = "y" }}
        }.AsQueryable();

        // Act
        var cast = qry.Count(x=>(x.Employee as Worker).Other == "x");
        var castDynamic = ????

        // Assert
        Check.That(cast).Equals(castDynamic);
    }

Or similar to one you referred to but for case when property is an object.

    public void Test2()
    {
        // Assign
        var qry = new[]
        {
            new { Employee = (BaseEmployee)new Worker { Name = "1", Other = "x" }},
            new { Employee = (BaseEmployee)new Boss { Name = "2", Function = "y" }}
        }.AsQueryable();

        // Act
        var cast = qry.Select(x=>(x.Employee is Worker) ? (x.Employee as Worker).Other : "-").ToArray();
        var castDynamic = ????

        // Assert
        Check.That(cast.Length).Equals(castDynamic.Length);
    }

@StefH StefH reopened this Feb 19, 2022
@StefH
Copy link
Collaborator

StefH commented Feb 19, 2022

@dsidedp
I understand.

This is not yet supported, but this can be added.

Would this syntax be ok?

        [Fact]
        public void IsAndCastToType_Dynamic_ActingOnProperty_And_GetProperty()
        {
            // Assign
            var qry = new []
            {
                new EmployeeWrapper { Employee = new Worker { Name = "1", Other = "x" } }, 
                new EmployeeWrapper { Employee = new Boss { Name = "2", Function = "y" } }
            }.AsQueryable();

            // Act
            var cast = qry.Select(c => c.Employee is Worker ? ((Worker) c.Employee).Other : "-").ToArray();
            var castDynamic = qry.Select("iif(Is(Employee, \"System.Linq.Dynamic.Core.Tests.Entities.Worker\"), Cast(Employee, \"System.Linq.Dynamic.Core.Tests.Entities.Worker\").Other, \"-\")").ToDynamicArray();

            // Assert
            Check.That(cast.Length).Equals(castDynamic.Length);
        }

@dsidedp
Copy link
Author

dsidedp commented Feb 19, 2022

Sure.

IMHO, that's the simplest and most obvious syntax. (assuming simple type resolution will be supported here)

@StefH
Copy link
Collaborator

StefH commented Feb 19, 2022

simple type resolution will be supported with:

var config = new ParsingConfig
{
  ResolveTypesBySimpleName = true
};

@StefH
Copy link
Collaborator

StefH commented Feb 19, 2022

A new version will be released soon.

#567

@StefH StefH closed this as completed Feb 19, 2022
@dsidedp
Copy link
Author

dsidedp commented Feb 19, 2022

Thank you for the fast update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants