Есть ли способ настроить Func с универсальным параметром объекта? - PullRequest
1 голос
/ 13 августа 2010

В настоящее время у меня есть настройка отображения для преобразования из одного базового класса в другой базовый класс. Я сопоставляю класс клиента стороннему контролю. Значения схожи, но есть достаточно различий, поэтому я не могу использовать сторонний элемент управления.

_converters = new Dictionary<Type, Func<AnnotationBase, AnnotationMark>>();
_converters.Add( typeof( HighlightAnnotation ), ToHighlighterAnnotationMark );
_converters.Add( typeof( RectangleAnnotation ), ToRedactionAnnotationMark );
_converters.Add( typeof( StampAnnotation ), ToTextStampAnnotationMark );

Это работает находка, но в некоторых местах мне приходится делать дополнительный каст. Например:

private AnnotationMark ToTextStampAnnotationMark( AnnotationBase tool )
{
    TextStampAnnotationMark mark = new TextStampAnnotationMark();
    mark.Location = new MarkLocation { X = (int)tool.Location.X, Y = (int)tool.Location.Y };
    mark.Size = new MarkSize { Width = (int)tool.Size.Width, Height = (int)tool.Size.Height };
    mark.Text = ((StampAnnotation)tool).Text;
    return mark;
}

В этом примере я должен указать, что AnnotationBase будет StampAnnotation, что, как я знаю, является правильным, поскольку это тип, зарегистрированный в маппере. Однако я бы хотел изменить сигнатуру этого метода на private TextStampAnnotationMark ToTestStampAnnotationMark( StampAnnotaion ).

Есть ли способ сделать отображение функции или вести себя так?

Func<TTool,TMark>() 
    where TTool : AnnotationBase 
    where TMark : AnnotationMark

Ответы [ 2 ]

0 голосов
/ 13 августа 2010

Вроде как глупо, что я не подумала об этом. Простое решение - забрать объект до регистрации.

converters.Add( typeof( StampAnnotation ), 
    tool => ToTextStampAnnotationMark( (StampAnnotation)tool ); 
0 голосов
/ 13 августа 2010

Это точно не отвлекает вас от использования кастов, но централизует их и делает их «безопасными»:

static class ConvertTest
{
    static IDictionary<Type, IDictionary<Type, Func<AnnotationBase, AnnotationMark>>> _conversions =
        new Dictionary<Type, IDictionary<Type, Func<AnnotationBase, AnnotationMark>>>();

    public static TTo Convert<TFrom, TTo>(this TFrom source)
        where TFrom : AnnotationBase
        where TTo : AnnotationMark
    {
        var conversion = _conversions[typeof(TFrom)][typeof(TTo)];
        return (TTo)conversion(source);
    }

    public static void RegisterConversion<TFrom, TTo>(Func<TFrom, TTo> conversion)
        where TFrom : AnnotationBase
        where TTo : AnnotationMark
    {
        IDictionary<Type, Func<AnnotationBase, AnnotationMark>> toDictionary;

        if (!_conversions.TryGetValue(typeof(TFrom), out toDictionary))
        {
            toDictionary = new Dictionary<Type, Func<AnnotationBase, AnnotationMark>>();
            _conversions.Add(typeof(TFrom), toDictionary);
        }

        toDictionary[typeof(TTo)] = (Func<AnnotationBase, AnnotationMark>)conversion;
    }
}

Кстати, я не тестировал этот код (хотя он компилируется :)).

...