简体   繁体   中英

C# get nullable datetime ToString format method with params to set Expression.Call

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? .

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]));
        }

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);
    }
}

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..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM