Punica.Linq.Dynamic 2.0.0

dotnet add package Punica.Linq.Dynamic --version 2.0.0
                    
NuGet\Install-Package Punica.Linq.Dynamic -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Punica.Linq.Dynamic" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Punica.Linq.Dynamic" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Punica.Linq.Dynamic" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Punica.Linq.Dynamic --version 2.0.0
                    
#r "nuget: Punica.Linq.Dynamic, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Punica.Linq.Dynamic@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Punica.Linq.Dynamic&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Punica.Linq.Dynamic&version=2.0.0
                    
Install as a Cake Tool

Dynamic Expression

A Simple text parse which convert expression from a string to Lambda Expression.

Installing Dynamic Expression

You should install Punica.Linq.Dynamic

Install-Package Punica.Linq.Dynamic

Or via the .NET Core command line interface:

dotnet add package Punica.Linq.Dynamic

Either commands, from Package Manager Console or .NET Core CLI, will download and install Punica.Linq.Dynamic and all required dependencies.

How to use

Common Methods Used in Samples

public Expression<Func<TResult>> GetExpression<TResult>(string expression)
{
    var eval = new Evaluator();
    return eval.Parse<Expression<Func<TResult>>>(expression);
}

public Expression<Func<T1, TResult>> GetExpression<T1, TResult>(string expression)
{
    var eval = new Evaluator()
        .AddStartParameter(typeof(T1));
    return eval.Parse<Expression<Func<T1, TResult>>>(expression);
}

public LambdaExpression GetGeneralExpression<T1>(string expression)
{
    var eval = new Evaluator()
        .AddStartParameter(typeof(T1));
    return eval.Parse(expression);
}

Addition

 string stringExp = "5 + 7";

 var resultExpression = GetExpression<int>(stringExp);
 var result = resultExpression.Compile()(); // 12

Contains

string stringExp = $"'rl' in 'hello world'";
var resultExpression = GetExpression<bool>(stringExp);
var result = resultExpression.Compile()(); // true
public class MyList
{    
    public List<Status> Statuses { get; set; }
}

var data = new MyList(){
     Statuses = new List<Status>()
     {
         Status.Active,
         Status.Inactive,
         Status.Online,
         Status.Paused
     }
}  
string expression= $"'Status.Active' in Statuses";

var resultExpression = GetExpression<MyList, bool>(expression);
Func<MyList, bool> func = resultExpression.Compile();

var result = func(data); // true
public class Person
{
   public Guid Id { get; set; }
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public List<Child> Children { get; set; }
}
public class Child
{
   public string Name { get; set; }
   public string Gender { get; set; }
}

public class MyList
{    
    public List<Person> Persons { get; set; }
}

var data = new MyList(){
    Persons = new List<Person>(){
    --- Your Data --
    }
}  

string expression= $"Select(new{ FirstName,Children.Select(new{Name , Gender}).ToList() as 'Kids'}).Where(Kids.Any(Gender == 'Female'))";
var resultExpression = GetGeneralExpression<IQueryable<Person>>(stringExp);
var function = resultExpression.Compile();
var result = function(data.Persons.AsQueryable());

// data.Persons.AsQueryable() can be something like _context.Persons in EF Core DB context scenario. In that case, code equivalant to above string expression looks like following

  _context.Persons..Select(x => new
    {
        FirstName = x.FirstName,
        Kids = x.Children.Select(c => new
        {
            c.Name,
            Gender = c.Gender
        }).ToList(),
    }).Where(p => p.Kids.Any(k => k.Gender == "Female"));
	

Features

  • Support equality operators: ==,!=
  • Support relational operators: >,>=,<=,<
  • Support Conditional operators ??,?
  • Arithmetic Operators: +,-,/,*,%
  • New expressions new
  • Bitwise And and Or Operations: &,|
  • String Operations: Contains,+, Trim, StartsWith,Substring etc.
  • Linq Methods: Linq Methods
  • Precedence using parenthesis (,)
  • Lambda calls
  • Aliases
Alias Operator Name Symbol Alias Operator Name Symbol
eq Equal == not Not !
ne NotEqual != add Add +
lt LessThan < sub Subtract -
le LessThanOrEqual <= mul Multiply *
gt GreaterThan > div Divide /
ge GreaterThanOrEqual >= true BooleanLiteral (True) true
in Contain in false BooleanLiteral (False) false
as As, Variable Rename as null Null null
or OrElse <code>||</code> new New, Create new Instances new
and AndAlso && mod Modulo %

Limitation

  • Linq methods (All Enumerable,Queryable methods supported but haven't test all out).
  • Dates and GUID operation has very little support if they are inputs.
  • Adding Custom types for dynamic method detection.

Improvements

  • Overall tokens detections
  • Better number type support
  • Most Linq limitation removed
  • Dynamic method detection support compared to previous static definition but slower compared previous implementation.
  • Limit dynamic methods for only know namespaces for security consideration.
  • Will interpret types based on expression, will fail if it can't determine the overload
  • Method chaining support.
Method Mean Error StdDev Gen0 Gen1 Allocated
Two_Select_With_New_Expression 18.931 μs 0.3485 μs 0.3260 μs 2.8076 - 23.25 KB
Select_With_New_Expression 8.746 μs 0.0788 μs 0.0737 μs 1.1597 - 9.86 KB
Advanced_Boolean_Expression 3.129 μs 0.0532 μs 0.0498 μs 0.5035 0.0038 4.13 KB
Average_Int_With_Predicate 9.644 μs 0.1402 μs 0.1312 μs 1.2512 - 10.37 KB
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 219 7/27/2025
1.0.0 240 7/20/2024
0.3.1 301 5/7/2023
0.3.0 289 4/29/2023
0.2.0 296 4/27/2023
0.1.1 296 4/26/2023
0.1.0 212 4/25/2023