我想实现一个泛型类型映射器,我正在努力解决与泛型类型约束相关的问题。
我有以下定义的实体映射器类:
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?
之间的映射代码报告为错误。它甚至不会报告错误映射decimal? -> decimal
(它将在运行时中断)。
编译器报告错误的唯一地方是我想要投射string -> decimal?
的行。
所以我有以下问题:
欢迎任何其他建议,评论。
答案 0 :(得分:0)
mapper.RegisterMapping(x => x.FooLongProp, x => x.BarLongNullProp, x => x); // FooLongProp -> long, BarLongNullProp -> long?
x => x.FooLongProp
编译器推断(Expression<Func<Foo, long>>
)x => x.BarLongNullProp
编译器推断(Expression<Func<Bar, long?>>
)x => x
编译器推断(Func<long, long?>>
)mapper.RegisterMapping(x => x.FooDecimalNullProp, x => x.BarLongNullProp, x => x); // FooDecimalNullProp -> decimal?, BarLongNullProp -> long?
x => x.FooDecimalNullProp
编译器推断(Expression<Func<Foo, decimal?>>
)
x => x
编译器推断(Func<decimal?, decimal?>>
)!!为什么??因为x=>x
是Func<type of x,type of x>
x => x.BarLongNullProp
编译器推断(Expression<Func<Bar, decimal?>>
)!!为什么?因为第2行它向long?
转发decimal?
所以它可以匹配通用参数。
Func<string, long?>
。当您提供x=>x
(Func<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?