Возможно ли сделать upcast делегата Func?

Упрощенный абстрактный пример. Есть ExceptionMapper, который должен уметь настраивать маппинг SomeException -> SomeObj и конвертировать объект типа SomeException в JSON строку, представленную в виде объекта SomeObject. Код консольного приложения (.net-8) ниже.

Основная проблема - хранить маппинг для определенного Exception. Маппинг представлен делегатом Func<T, TObj> mapFn where T: Exception where TObj: class. Я объявил словарь:

private static Dictionary<string, Func<Exception, object>> _map = new();

Казалось бы, что тип Exception шире, чем любой из возможных <T> where T: Exception. Также и object будет шире любого типа <TObj> where TObj: class, но такой upcast возвращает null:

public static void AddMapping<T, TObj>(Func<T, TObj> mapFn) where T: Exception where TObj: class
{
    _map.Add(typeof(T).Name, mapFn as Func<Exception, object>); // <-- Тут upcast возвращает null
}

Вопросы:

  1. Почему такой upcast не срабатывает как ожидается?
  2. Как изменить мой пример, чтобы ожидаемое поведение работало?

Полный код (можно вставить в Program.cs консольного приложения и запускать):

using System.Text.Json;

ExceptionMapper.AddMapping((ApplicationException ex) => new { Message = ex.Message });

var result = ExceptionMapper.MapToJson(new ApplicationException("App crushed"));

Console.WriteLine(result);

static class ExceptionMapper
{
    private static Dictionary<string, Func<Exception, object>> _map = new();
    
    public static void AddMapping<T, TObj>(Func<T, TObj> mapFn) where T: Exception where TObj: class
    {
        _map.Add(typeof(T).Name, mapFn as Func<Exception, object>); // <-- Тут upcast возвращает null
    }

    public static string MapToJson<T>(T ex) where T : Exception
    {
        if (!_map.TryGetValue(ex.GetType().Name, out var mapFn))
        {
            return JsonSerializer.Serialize(new {});
        }

        if (mapFn == null)
        {
            throw new Exception($"mapFn is null for mapped exception {ex.GetType().Name}"); // <-- Бросится exception
        }

        var obj = mapFn(ex);
        return JsonSerializer.Serialize(obj);
    }
}

Вывод в консоли:

Unhandled exception. System.Exception: mapFn is null for mapped exception ApplicationException


Ответы (0 шт):