C
C#3mo ago
SWEETPONY

✅ How to correctly write conditions with expressions?

I have this code:
public static class BookPolicy
{
public static void AllowRead(Book book)
{
var isHorrorBook = Specifications.IsHorrorBook().Compile();
var isPonyBook = Specifications.IsPonyBook().Compile();

if (isHorrorBook(book) || isPonyBook(book))
throw new Exception("Horror or pony books don't allow here");
}
}

public static class Specifications
{
public static Expression<Func<Book, bool>> IsHorrorBook() =>
book => book.Title.Contains("Frankenstein");

public static Expression<Func<Book, bool>> IsPonyBook() =>
book => book.Title.Contains("Pony");
}
public static class BookPolicy
{
public static void AllowRead(Book book)
{
var isHorrorBook = Specifications.IsHorrorBook().Compile();
var isPonyBook = Specifications.IsPonyBook().Compile();

if (isHorrorBook(book) || isPonyBook(book))
throw new Exception("Horror or pony books don't allow here");
}
}

public static class Specifications
{
public static Expression<Func<Book, bool>> IsHorrorBook() =>
book => book.Title.Contains("Frankenstein");

public static Expression<Func<Book, bool>> IsPonyBook() =>
book => book.Title.Contains("Pony");
}
everything is ok but i would like to know is it possible to write smth like this? if(book is Horror or Pony) {...} I don't understand how to do this with expressions
2 Replies
Anton
Anton3mo ago
yes Well, not exactly But similar I think you can do
(book.GetType() == typeof(Horror) || book.GetType() == typeof(Pony)) ? DoStuff1() : DoStuff2()
(book.GetType() == typeof(Horror) || book.GetType() == typeof(Pony)) ? DoStuff1() : DoStuff2()
chatgpt at work (it's just tedious to write out manually)
using System;
using System.Linq.Expressions;

public class Book { }
public class Horror : Book { }
public class Pony : Book { }

public class Program
{
public static void Main()
{
// Assuming these are the provided expressions
Expression<Func<Book, bool>> isHorror = book => book.GetType() == typeof(Horror);
Expression<Func<Book, bool>> isPony = book => book.GetType() == typeof(Pony);

ParameterExpression bookParam = isHorror.Parameters[0];

var parameterReplacer = new ParameterReplacer(bookParam);
Expression isPonyReplaced = parameterReplacer.Visit(isPony.Body);

Expression combinedCondition = Expression.OrElse(isHorror.Body, isPonyReplaced);

MethodCallExpression doStuff1Call = Expression.Call(typeof(Program).GetMethod(nameof(DoStuff1)));
MethodCallExpression doStuff2Call = Expression.Call(typeof(Program).GetMethod(nameof(DoStuff2)));

Expression ternaryExpression = Expression.Condition(combinedCondition, doStuff1Call, doStuff2Call);

var lambda = Expression.Lambda<Action<Book>>(ternaryExpression, bookParam);
}

public static void DoStuff1()
{
Console.WriteLine("DoStuff1 called");
}

public static void DoStuff2()
{
Console.WriteLine("DoStuff2 called");
}

// Helper class to replace parameters in an expression
private class ParameterReplacer : ExpressionVisitor
{
private readonly ParameterExpression _parameter;

public ParameterReplacer(ParameterExpression parameter)
{
_parameter = parameter;
}

protected override Expression VisitParameter(ParameterExpression node)
{
return _parameter; // Replace with the correct parameter
}
}
}
using System;
using System.Linq.Expressions;

public class Book { }
public class Horror : Book { }
public class Pony : Book { }

public class Program
{
public static void Main()
{
// Assuming these are the provided expressions
Expression<Func<Book, bool>> isHorror = book => book.GetType() == typeof(Horror);
Expression<Func<Book, bool>> isPony = book => book.GetType() == typeof(Pony);

ParameterExpression bookParam = isHorror.Parameters[0];

var parameterReplacer = new ParameterReplacer(bookParam);
Expression isPonyReplaced = parameterReplacer.Visit(isPony.Body);

Expression combinedCondition = Expression.OrElse(isHorror.Body, isPonyReplaced);

MethodCallExpression doStuff1Call = Expression.Call(typeof(Program).GetMethod(nameof(DoStuff1)));
MethodCallExpression doStuff2Call = Expression.Call(typeof(Program).GetMethod(nameof(DoStuff2)));

Expression ternaryExpression = Expression.Condition(combinedCondition, doStuff1Call, doStuff2Call);

var lambda = Expression.Lambda<Action<Book>>(ternaryExpression, bookParam);
}

public static void DoStuff1()
{
Console.WriteLine("DoStuff1 called");
}

public static void DoStuff2()
{
Console.WriteLine("DoStuff2 called");
}

// Helper class to replace parameters in an expression
private class ParameterReplacer : ExpressionVisitor
{
private readonly ParameterExpression _parameter;

public ParameterReplacer(ParameterExpression parameter)
{
_parameter = parameter;
}

protected override Expression VisitParameter(ParameterExpression node)
{
return _parameter; // Replace with the correct parameter
}
}
}
also fyi they aren't cached the whole tree gets recreated each time you call that method make it a readonly field for it to get cached
SWEETPONY
SWEETPONY3mo ago
ah thanks for helping me
Want results from more Discord servers?
Add your server