有没有办法用通用对象参数设置Func?

时间:2010-08-13 14:45:49

标签: c# generics .net-4.0 mapping function-pointers

我目前有一个映射设置,可以从一个基类转换为另一个基类。我正在将客户类映射到第三方控件。值是相似的,但有足够的差异,我不能重复使用第三方控件。

_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;
}

在这个例子中,我必须假设AnnotationBaseStampAnnotation我知道恰好是正确的,因为这是在mapper中注册的类型。但是,我很乐意将此方法的签名更改为private TextStampAnnotationMark ToTestStampAnnotationMark( StampAnnotaion )

无论如何都要进行功能映射或表现如下吗?

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

2 个答案:

答案 0 :(得分:0)

这并不能完全避免使用任何演员阵容,但它会集中他们并使他们“安全”:

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;
    }
}

顺便说一下,我没有测试过这段代码(但是编译了:)。

答案 1 :(得分:0)

有点愚蠢,我没有想到它是正确的方式。简单的解决方案是在注册之前投射对象。

converters.Add( typeof( StampAnnotation ), 
    tool => ToTextStampAnnotationMark( (StampAnnotation)tool );