
本文共 9681 字,大约阅读时间需要 32 分钟。
������������������������������������ C# 9 ���record���������������������id���������������
public record ProductId(int Value);
������������������id���������������������������������������������������������������ASP.NET Core������������������������������������������������������������������������������������������������������������������������������������������������
���������������������������������������������
���������������������������������������
public record ProductId(int Value);public class Product{ public ProductId Id { get; set; } public string Name { get; set; } public decimal UnitPrice { get; set; }}
������������API���������
[ApiController][Route("api/[controller]")]public class ProductController : ControllerBase{ ... [HttpGet("{id}")] public ActionResultGetProduct(ProductId id) { return Ok(new Product { Id = id, Name = "Apple", UnitPrice = 0.8M }); }}
������������������������Get������������������������ /api/product/1
���
{ "type": "https://tools.ietf.org/html/rfc7231#section-6.5.13", "title": "Unsupported Media Type", "status": 415, "traceId": "00-3600640f4e053b43b5ccefabe7eebd5a-159f5ca18d189142-00"}
���������������������������������415���.NET Core ������������������URL������������������ProductId������������������int������������������������������ID������������������������������������������
���������������������
������������������������������������������������������ProductId���������������
public class ProductIdConverter : TypeConverter{ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) => sourceType == typeof(string); public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => destinationType == typeof(string); public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { return value switch { string s => new ProductId(int.Parse(s)), null => null, _ => throw new ArgumentException($"Cannot convert from {value} to ProductId", nameof(value)) }; } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(string)) { return value switch { ProductId id => id.Value.ToString(), null => null, _ => throw new ArgumentException($"Cannot convert {value} to string", nameof(value)) }; } throw new ArgumentException($"Cannot convert {value ?? "(null)"} to {destinationType}", nameof(destinationType)); }}
������������������������������������������������������string,������������������������������������������������������int���
���������ProductId������TypeConverter������������������������������������������
[TypeConverter(typeof(ProductIdConverter))]public record ProductId(int Value);
���������������������������������������������������
{ "id": { "value": 1 }, "name": "Apple", "unitPrice": 0.8}
���������������������������������������������id ���json������������������������������������json������������������������������������������������������������������������������������������������������ProductId������������������������������������������������������������������������������������������������������������������������������
���������������id���������
������������������������������Helper
- ������������������������������ID������������������������
- ������������������������������������������������
public static class StronglyTypedIdHelper{ private static readonly ConcurrentDictionaryStronglyTypedIdFactories = new(); public static Func GetFactory (Type stronglyTypedIdType) where TValue : notnull { return (Func )StronglyTypedIdFactories.GetOrAdd( stronglyTypedIdType, CreateFactory ); } private static Func CreateFactory (Type stronglyTypedIdType) where TValue : notnull { if (!IsStronglyTypedId(stronglyTypedIdType)) throw new ArgumentException($"Type '{stronglyTypedIdType}' is not a strongly-typed id type", nameof(stronglyTypedIdType)); var ctor = stronglyTypedIdType.GetConstructor(new[] { typeof(TValue) }); if (ctor is null) throw new ArgumentException($"Type '{stronglyTypedIdType}' doesn't have a constructor with one parameter of type '{typeof(TValue)}'", nameof(stronglyTypedIdType)); var param = Expression.Parameter(typeof(TValue), "value"); var body = Expression.New(ctor, param); var lambda = Expression.Lambda >(body, param); return lambda.Compile(); } public static bool IsStronglyTypedId(Type type) => IsStronglyTypedId(type, out _); public static bool IsStronglyTypedId(Type type, [NotNullWhen(true)] out Type idType) { if (type is null) throw new ArgumentNullException(nameof(type)); if (type.BaseType is Type baseType && baseType.IsGenericType && baseType.GetGenericTypeDefinition() == typeof(StronglyTypedId<>)) { idType = baseType.GetGenericArguments()[0]; return true; } idType = null; return false; }}
������ Helper ������������������������������������������������������������������������������������
public class StronglyTypedIdConverter: TypeConverter where TValue : notnull{ private static readonly TypeConverter IdValueConverter = GetIdValueConverter(); private static TypeConverter GetIdValueConverter() { var converter = TypeDescriptor.GetConverter(typeof(TValue)); if (!converter.CanConvertFrom(typeof(string))) throw new InvalidOperationException( $"Type '{typeof(TValue)}' doesn't have a converter that can convert from string"); return converter; } private readonly Type _type; public StronglyTypedIdConverter(Type type) { _type = type; } public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string) || sourceType == typeof(TValue) || base.CanConvertFrom(context, sourceType); } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { return destinationType == typeof(string) || destinationType == typeof(TValue) || base.CanConvertTo(context, destinationType); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value is string s) { value = IdValueConverter.ConvertFrom(s); } if (value is TValue idValue) { var factory = StronglyTypedIdHelper.GetFactory (_type); return factory(idValue); } return base.ConvertFrom(context, culture, value); } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (value is null) throw new ArgumentNullException(nameof(value)); var stronglyTypedId = (StronglyTypedId )value; TValue idValue = stronglyTypedId.Value; if (destinationType == typeof(string)) return idValue.ToString()!; if (destinationType == typeof(TValue)) return idValue; return base.ConvertTo(context, culture, value, destinationType); }}
��������������������������������� Converter
public class StronglyTypedIdConverter : TypeConverter{ private static readonly ConcurrentDictionaryActualConverters = new(); private readonly TypeConverter _innerConverter; public StronglyTypedIdConverter(Type stronglyTypedIdType) { _innerConverter = ActualConverters.GetOrAdd(stronglyTypedIdType, CreateActualConverter); } public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) => _innerConverter.CanConvertFrom(context, sourceType); public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) => _innerConverter.CanConvertTo(context, destinationType); public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) => _innerConverter.ConvertFrom(context, culture, value); public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) => _innerConverter.ConvertTo(context, culture, value, destinationType); private static TypeConverter CreateActualConverter(Type stronglyTypedIdType) { if (!StronglyTypedIdHelper.IsStronglyTypedId(stronglyTypedIdType, out var idType)) throw new InvalidOperationException($"The type '{stronglyTypedIdType}' is not a strongly typed id"); var actualConverterType = typeof(StronglyTypedIdConverter<>).MakeGenericType(idType); return (TypeConverter)Activator.CreateInstance(actualConverterType, stronglyTypedIdType)!; }}
��������������������������������������������� ProductIdConvert��� ���������������������������������������������.NET Core ���������������������������������������������������������������������������������������JSON���������������������
[TypeConverter(typeof(StronglyTypedIdConverter))]public abstract record StronglyTypedId(TValue Value) where TValue : notnull{ public override string ToString() => Value.ToString();}
������������: thomas levesque
���������������
������
������������������������������������ ���������������������������������������������������������������������������������������������������QQ��� 897216102