簡體   English   中英

泛型類型中的精確類型約束 - C#

[英]Exact type constraints in generic types - C#

我想實現一個泛型類型映射器,我正在努力解決與泛型類型約束相關的問題。

我有和實體映射器類定義如下:

public class EntityMapper<TDto, TEntity>
{
    public void RegisterMapping<TDtoProperty, TEntityProperty>(
        Expression<Func<TDto, TDtoProperty>> expressionFrom,
        Expression<Func<TEntity, TEntityProperty>> expressionTo,
        Func<TDtoProperty, TEntityProperty> mapper)
    {
        // mapping
    }
}

我還有2個類我要映射的屬性:

public class Foo
{
    public long FooLongProp { get; set; }

    public decimal? FooDecimalNullProp { get; set; }

    public string FooStringProp { get; set; }
}

public class Bar
{
    public long? BarLongNullProp { get; set; }

    public decimal BarDecimalProp { get; set; }
}

映射正在執行如下:

public void Map()
{
    var mapper = new EntityMapper<Foo, Bar>();

    mapper.RegisterMapping(x => x.FooLongProp, x => x.BarLongNullProp, x => x); // FooLongProp -> long, BarLongNullProp -> long?
    mapper.RegisterMapping(x => x.FooDecimalNullProp, x => x.BarLongNullProp, x => x); // FooDecimalNullProp -> decimal?, BarLongNullProp -> long?
    mapper.RegisterMapping(x => x.FooDecimalNullProp, x => x.BarDecimalProp, x => x); // FooDecimalNullProp -> decimal?, BarDecimalProp -> decimal

    mapper.RegisterMapping(x => x.FooStringProp, x => x.BarLongNullProp, x => x); // FooStringProp -> string, BarLongNullProp -> long?
}

我希望RegisterMapping的第三個參數返回與TEntityProperty完全相同的類型。 不幸的是編譯器沒有報告long -> long?之間的映射代碼long -> long? 以下是一個錯誤。 它甚至不報告錯誤映射decimal? -> decimal decimal? -> decimal (將在運行時中斷)。

編譯器報告錯誤的唯一地方是我想要轉換string -> decimal?

所以我有以下問題:

  1. 為什么前3個映射不能像我預期的那樣工作? 似乎編譯器無法正確解析其類型。
  2. 有沒有辦法在通用約束中指定完全相同的類型約束?
  3. 有沒有其他的可能性來實現我想要做的事情並在編譯期間獲得錯誤?

任何其他建議,歡迎評論。

mapper.RegisterMapping(x => x.FooLongProp, x => x.BarLongNullProp, x => x); // FooLongProp -> long, BarLongNullProp -> long?
  1. x => x.FooLongProp編譯器推斷( Expression<Func<Foo, long>>
  2. x => x.BarLongNullProp編譯器推斷( Expression<Func<Bar, long?>>
  3. x => x編譯器推斷( Func<long, long?>>

mapper.RegisterMapping(x => x.FooDecimalNullProp, x => x.BarLongNullProp, x => x); // FooDecimalNullProp -> decimal?, BarLongNullProp -> long?
  1. x => x.FooDecimalNullProp編譯器推斷( Expression<Func<Foo, decimal?>>

  2. x => x編譯器推斷( Func<decimal?, decimal?>> )!! 為什么?? 因為x=>xFunc<type of x,type of x>

  3. x => x.BarLongNullProp編譯器推斷( Expression<Func<Bar, decimal?>> )!! 為什么? 因為2號線它翻了long? decimal? 所以它可以匹配通用參數。


在其他情況下發生類似的事情。 在最后一種情況下,編譯器查找Func<string, long?> 當你提供x=>xFunc<string,string> )時,編譯器無法推斷出你的泛型類型的正確類型,因此它會失敗。 將鼠標光標懸停在方法調用上將顯示編譯器推斷的泛型參數。 也許你應該為你的lambdas指定一個顯式的輸入。

mapper.RegisterMapping(x => x.FooLongProp, x => x.BarLongNullProp, x => x); 
mapper.RegisterMapping(x => x.FooDecimalNullProp, x => x.BarLongNullProp, x => (long?)x);
mapper.RegisterMapping(x => x.FooDecimalNullProp, x => x.BarDecimalProp, x => (decimal)x); 

mapper.RegisterMapping(x => x.FooStringProp, x => x.BarLongNullProp, x => (long?)(object)x ); //or any lambda which returns long?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM