-
Notifications
You must be signed in to change notification settings - Fork 13
Binding converters
Adam Bajguz edited this page Dec 19, 2021
·
1 revision
Typin supports custom binding converters. Simply initialize Converter
property in CommandOptionAttribute
or CommandParameterAttribute
with a converter type. A converter type is a class that inherits BindingConverter<TProperty>
[Command("cmd")]
public class SupportedArgumentTypesViaConverterCommand : SelfSerializeCommandBase
{
[CommandOption("str-class", Converter = typeof(InitializableClassTypeByConverter_Converter))]
public InitializableClassTypeByConverter? StringInitializable { get; init; }
}
public class InitializableClassTypeByConverter
{
public int Value { get; init; }
public DayOfWeek Day { get; init; }
}
public class InitializableClassTypeByConverter_Converter : BindingConverter<InitializableClassTypeByConverter>
{
public override InitializableClassTypeByConverter? Convert(string? value)
{
if (value is null)
{
return null;
}
string[] values = value.Split(':');
if (values.Length != 2)
{
throw new FormatException($"Invalid format of {nameof(InitializableClassTypeByConverter)}.");
}
DayOfWeek day = Enum.Parse<DayOfWeek>(values[0]);
int v = int.Parse(values[1]);
return new InitializableClassTypeByConverter { Value = v, Day = day };
}
public override InitializableClassTypeByConverter ConvertCollection(IReadOnlyCollection<string> values)
{
throw new NotImplementedException();
}
}
TIP: Nullable struct can be initialized by non-nullable converter.
[Command("cmd")]
public class SupportedArgumentTypesViaConverterCommand : SelfSerializeCommandBase
{
[CommandOption("str-nullable-struct-by-non-nullable-converter", Converter = typeof(InitializableStructTypeByConverter_Converter))]
public InitializableStructTypeByConverter? StringNullableInitializableStructByNonNullableConverter { get; init; }
[CommandOption("str-struct", Converter = typeof(InitializableStructTypeByConverter_Converter))]
public InitializableStructTypeByConverter StringInitializableStruct { get; init; }
}
public struct InitializableStructTypeByConverter
{
public int Value { get; init; }
public DayOfWeek Day { get; init; }
}
public class InitializableStructTypeByConverter_Converter : BindingConverter<InitializableStructTypeByConverter>
{
public override InitializableStructTypeByConverter Convert(string? value)
{
if (value is null)
{
return default;
}
string[] values = value.Split(':');
if (values.Length != 2)
{
throw new FormatException($"Invalid format of {nameof(InitializableClassTypeByConverter)}.");
}
DayOfWeek day = Enum.Parse<DayOfWeek>(values[0]);
int v = int.Parse(values[1]);
return new InitializableStructTypeByConverter { Value = v, Day = day };
}
public override InitializableStructTypeByConverter ConvertCollection(IReadOnlyCollection<string> values)
{
throw new NotImplementedException();
}
}
[Command("cmd")]
public class SupportedArgumentTypesViaConverterCommand : SelfSerializeCommandBase
{
[CommandOption("str-enumerable", Converter = typeof(InitializableEnumerableByConverter_Converter<string>))]
public InitializableEnumerableByConverter<string>? StringEnumerableInitializable { get; init; }
[CommandOption("str-indirect-enumerable", Converter = typeof(InitializableEnumerableByConverter_Converter<string>))]
public InitializableEnumerableByConverter? IndirectlyStringEnumerableInitializable { get; init; }
}
public abstract class InitializableEnumerableByConverter : IEnumerable
{
public abstract IEnumerator GetEnumerator();
}
public class InitializableEnumerableByConverter<T> : InitializableEnumerableByConverter, IEnumerable<T>
{
private readonly IEnumerable<T> _arr;
public InitializableEnumerableByConverter(IEnumerable<T> value)
{
_arr = value;
}
public override IEnumerator<T> GetEnumerator()
{
return _arr.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class InitializableEnumerableByConverter_Converter<T> : BindingConverter<InitializableEnumerableByConverter<T>>
{
// This method is used by scalar binder or non-scalar binder (when a property is a collection of <typeparamref name="T"/> - conversion for collection item type).
public override InitializableEnumerableByConverter<T>? Convert(string? value)
{
if (value is null)
{
return null;
}
T[] values = value.Split(':').Cast<T>().ToArray();
return new InitializableEnumerableByConverter<T>(values);
}
// This method is used by non-scalar binder when converting collection type.
public override InitializableEnumerableByConverter<T> ConvertCollection(IReadOnlyCollection<string> values)
{
List<T> v = new();
foreach (string value in values)
{
v.AddRange(value.Split(':').Cast<T>());
}
return new InitializableEnumerableByConverter<T>(v);
}
}
Getting started
Advanced features
- Reporting errors
- Exception handling
- Metadata and startup message
- Graceful cancellation
- Dependency injection
- Middleware pipeline
- Environment variables
Utilities
Tests
Misc