LINQクエリ式を動的に作成する関数を作成する必要があります。Equals
aDateTimeOffset
をaと比較する式を作成できませんDateTimeOffset?
(Expression.Equal
タイプを比較できないと文句を言います)。また、使用する変換戦略に関係なく変換できないため、aDateTimeOffset
をaDateTimeOffset?
に変換して機能させるExpression.Equal
ことDateTimeOffset
もできません。DateTimeOffset?
。
MyEntity.cs:
public class MyEntity {
public DateTimeOffset? DeliverOn;
}
Main.cs:
public void Test {
IQueryable<MyEntity> MyEntityList = Enumerable.Empty<MyEntity>().AsQueryable();
DateTimeOffset? dt1 = new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero);
var expr = WhereEquals(MyEntityList, t => t.DeliverOn, dt1);
}
ExpressionBuilder.cs:
public static IQueryable<TSource> WhereEquals<TSource, TValue>(IQueryable<TSource> source, Expression<Func<TSource, TValue>> selector, TValue value) {
return source.Where(Expression.Lambda<Func<TSource, bool>>(Expression.Equal(selector.Body, Expression.Constant(value)), selector.Parameters));
}
スロー: System.InvalidOperationException: 'The binary operator Equal is not defined for the types 'System.Nullable``1[System.DateTimeOffset]' and 'System.DateTimeOffset'.'
にもかかわらずdt1
であるDateTimeOffset?
コンパイル時に、実行時に、C#は考えてdt1
いますDateTimeOffset
。これを解決できますか?
私が試してみました:
DateTimeOffset? dt1 = (DateTimeOffset?)new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero);
DateTimeOffset? dt1 = (DateTimeOffset?)(object)new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero);
DateTimeOffset? dt1 = (DateTimeOffset?)Convert.ChangeType(new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero), typeof());
ただし、dt1はまだDateTimeOffset
です。
オーバーロードExpression.Constant(Object, Type)
を使用して、比較に使用する値のタイプを指定します。
タイプを指定せずに、Nullable<DateTimeOffset>
単ににアンラップされていますDateTimeOffset
。
void Main()
{
//IQueryable<MyEntity> MyEntityList = Enumerable.Empty<MyEntity>().AsQueryable();
var MyEntityList = new List<MyEntity>();
MyEntityList.Add(new MyEntity { DeliverOn = new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero) });
DateTimeOffset? dt1 = new DateTimeOffset(2018, 01, 01, 00, 00, 00, TimeSpan.Zero);
var expr = WhereEquals<MyEntity, DateTimeOffset?>(MyEntityList.AsQueryable(), t => t.DeliverOn, (DateTimeOffset?)dt1);
Console.WriteLine($"{expr.Count()} item(s) found");
// Output:
// selector.GetType() is System.Linq.Expressions.Expression`1[System.Func`2[UserQuery + MyEntity, System.Nullable`1[System.DateTimeOffset]]]
// typeof(TValue) is System.Nullable`1[System.DateTimeOffset]
// value.GetType() is System.DateTimeOffset
// 1 item(s) found
}
public class MyEntity
{
public DateTimeOffset? DeliverOn;
}
public static IQueryable<TSource> WhereEquals<TSource, TValue>(IQueryable<TSource> source, Expression<Func<TSource, TValue>> selector, TValue value)
{
Console.WriteLine($"selector.GetType() is {selector.GetType()}");
Console.WriteLine($"typeof(TValue) is {typeof(TValue)}");
Console.WriteLine($"value.GetType() is {value.GetType()}");
return source.Where(Expression.Lambda<Func<TSource, bool>>(Expression.Equal(selector.Body, Expression.Constant(value, typeof(TValue))), selector.Parameters));
}
関連しますが、受け入れられた答えExpression.Convert()
は不要だと思います。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加