【发布时间】:2020-06-28 03:08:23
【问题描述】:
在使用 ProjectTo 查询时,是否有办法支持“包装”域模型作为映射中的结构?
例如,我有一个名为 Edition 的结构,它代表一个许可证版本。在数据库中,此类列存储为Integer。但是,在使用 WebApi 时,此类字段会以 struct Edition 的形式返回。您可能会问,如果它是 WebApi,只需在模型中返回 int 即可。好吧,这就是我们在幕后所做的,但我们还有一个用于 api 的 SDK,在这个 SDK 中,我们将返回的类建模为具有 Edition 而不是 int,因此开发人员很清楚什么数据的意思。
我们创建了 .net TypeConverters 和 Newtonjson 转换器,一切看起来都不错,除了 AutoMapper 在使用 ProjectTo<MyModel> 时抛出异常
Unable to create a map expression from ScriptVersion.License (System.Nullable`1[System.Int32]) to ScriptVersionModel.License (System.Nullable`1[Licensing.Edition])
Mapping types:
ScriptVersion -> ScriptVersionModel
Contracts.ScriptVersion -> Api.V10.ScriptVersionModel
Type Map configuration:
ScriptVersion -> ScriptVersionModel
Contracts.ScriptVersion -> Api.V10.ScriptVersionModel
Property:
License
Edition + EditionTypeConverter
[TypeConverter(typeof(EditionTypeConverter))]
[Serializable]
public struct Edition : ISerializable
{
/// <summary>
/// Prefer using <see cref="Edition.Community"/> instead.
/// This only exists to support using <see cref="Edition"/> on <see cref="System.Attribute"/>.
/// </summary>
public const int CommunityNumber = 1024;
/// <summary>
/// Prefer using <see cref="Edition.Standard"/> instead.
/// This only exists to support using <see cref="Edition"/> on <see cref="System.Attribute"/>.
/// </summary>
public const int StandardNumber = 1025;
/// <summary>
/// Prefer using <see cref="Edition.Enterprise"/> instead.
/// This only exists to support using <see cref="Edition"/> on <see cref="System.Attribute"/>.
/// </summary>
public const int EnterpriseNumber = 1026;
public static readonly Edition NotLicensed = new Edition(0);
public static readonly Edition Community = new Edition(CommunityNumber);
public static readonly Edition Standard = new Edition(StandardNumber);
public static readonly Edition Enterprise = new Edition(EnterpriseNumber);
private readonly int edition;
public Edition(int edition)
{
this.edition = edition;
}
public Edition(SerializationInfo info, StreamingContext context)
{
edition = (int)info.GetValue(nameof(edition), typeof(int));
}
public override string ToString()
{
if (edition == NotLicensed)
return "Not Licensed";
if (edition == Community)
return nameof(Community);
if (edition == Standard)
return nameof(Standard);
if (edition == Enterprise)
return nameof(Enterprise);
return $"Unknown({edition})";
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (!(obj is Edition))
return false;
var token = (Edition)obj;
return token.edition == edition;
}
public override int GetHashCode() => edition.GetHashCode();
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue(nameof(edition), edition);
}
public static bool operator !=(Edition left, Edition right) => !(left == right);
public static implicit operator int(Edition edition) => edition.edition;
public static bool operator ==(Edition left, Edition right)
{
if (ReferenceEquals(left, null))
return ReferenceEquals(right, null);
return left.Equals(right);
}
public static Edition? From(int? edition) => edition.HasValue ? new Edition(edition.Value) : (Edition?)null;
public class EditionTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType.GetActualType() == typeof(int) ||
sourceType.GetActualType() == typeof(long) ||
base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value == null)
return null;
if (int.TryParse(value.ToString(), out int edition))
return new Edition(edition);
if (long.TryParse(value.ToString(), out long longEdition))
return new Edition((int)longEdition);
return base.ConvertFrom(context, culture, value);
}
}
}
ScriptVersionModel - 从 WebApi 返回
public class ScriptVersionModel
{
public Edition? License{get;set;}
}
ScriptVersion - 实体框架类映射到数据库
public class ScriptVersion
{
public int? License{get;set;}
}
触发错误的代码
context.ScriptVersions.Where(predicate).ProjectTo<ScriptVersionModel>();
【问题讨论】:
-
CreateMap<Edition, int>()
标签: entity-framework automapper typeconverter webapi