Ответ на вопрос нашел:
Воспользуемся Type Converter.
Создадим класс EmotesConverter, зависимый от TypeConverter с таким содержимым:
public class EmotesConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) ||
base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return value is string emoteString
? Emote.Parse(emoteString)
: base.ConvertFrom(context, culture, value);
}
}
Добавим атрибут в класс опций:
[TypeConverter(typeof(EmotesConverter))]
public class EmotesOptions
{
public Emote CheckMark { get; set; }
public Emote Clock { get; set; }
}
И определим Type Converter при конфигурации сервисов:
public void ConfigureServices(IServiceCollection services)
{
TypeDescriptor.AddAttributes(typeof(Emote), new TypeConverterAttribute(typeof(EmotesConverter)));
services.Configure<EmotesOptions>(Configuration.GetSection("Emotes");
}