0

I'm trying to build dynamically build an expression LINQ function, when I do string comparison for datetime I get ToString method with format argument:

else if (member.Type == typeof(DateTime))
{
    var toString = typeof(DateTime).GetMethod("ToString", new Type[] { typeof(string) });
    member = Expression.Call(member, toString, Expression.Constant("yyyyMMdd"));
} 

I need to get ToString format method of DateTime?.

vasily.sib
  • 3,871
  • 2
  • 23
  • 26

3 Answers3

1

I would recommend building an expression like;

Expression<Func<T?, string>> expr = d => d.HasValue ? d.Value.ToString("...") : null;

For example;

        private static Dictionary<Type,string> Formats = ...

        private Expression ToString(Expression value)
        {
            if (value.Type.IsGenericType && value.Type.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                return Expression.Condition(
                    Expression.Property(value, "HasValue"),
                    ToString(Expression.Property(value, "Value")),
                    Expression.Constant(null, typeof(string))
                );
            }
            var toString = value.Type.GetMethod("ToString", new Type[] { typeof(string) });
            return Expression.Call(value, toString, Expression.Constant(Formats[value.Type]));
        }

Jeremy Lakeman
  • 9,515
  • 25
  • 29
0

Here a small example with a DateTime?. You have to handle the case where to value is null, makes no sense to call ToString() in this case.

public class Program
{
    public static void Main(string[] args)
    {
        DateTime? dateTime = ...;
        string result = "";

        if (dateTime.HasValue)
        {
            ConstantExpression constant = Expression.Constant(dateTime);
            MethodInfo? toString = typeof(DateTime).GetMethod("ToString", new[] { typeof(string) });
            MethodCallExpression call = Expression.Call(constant, toString, Expression.Constant("yyyyMMdd"));

            result = Expression.Lambda<Func<string>>(call).Compile()();
        }

        Console.WriteLine(result);
    }
}
Bidou
  • 7,378
  • 9
  • 47
  • 70
0

I'm not really sure what the relevance of the code block you pasted there is; is it you saying "this works for DateTime but not DateTime?" or is it you saying "this is what I'm trying to do with my DateTime?" ?

As such, I cant really tell you what to do but I can point out a couple of problems you'll encounter:

  • If your member.Type is returning a type of a DateTime? it won't ever be equal to a typeof(DateTime) because they are different types. Additionally, I'm not sure how member.Type comes to have a value but if it's via someInstance.GetType() you should bear in mind that calling GetType() on a null nullable throws a null reference exception. See GetType on Nullable Boolean for a lengthy discourse on this
  • a DateTime? doesn't have a ToString(string format) overload. You might need to implement something that checks if member.Type is a nullable type and then do your work with the nullable's .Value instead..
Caius Jard
  • 72,509
  • 5
  • 49
  • 80