有没有更好的方法来选择基于类类型的翻译方法?

时间:2013-05-30 20:23:20

标签: c# coding-style polymorphism

在我的代码中,我有一组对象,这些对象是不能使用新代码的类的实例。它们都需要转换为本地定义的相应类。我试图做一个干净的方法来确定实例所在的类的类型,并根据该类型调用适当的转换方法。但是,我似乎找不到像我想的那样干净利落的方法。这是我的代码。

using System;
using System.Collections.Generic;
using System.Linq;

namespace TranslatorSwitchExample
{
    public class Class1
    {
        void DoWork()
        {
            var oldTypes = new Base1[]
                {
                    new ClassA{ IntProperty = 1 },
                    new ClassB{ StringProperty = "test" }, 
                };
            var newTypes = TranslateAll(oldTypes);
        }

        static IEnumerable<Base2> TranslateAll(IEnumerable<Base1> oldTypes)
        {
            var newTypes = oldTypes.Select(x => TranslateByType[x.GetType()](x));
            return newTypes;
        }

        static readonly Dictionary<Type, Func<Base1, Base2>> TranslateByType =
            new Dictionary<Type, Func<Base1, Base2>>
                {
                    { typeof(ClassA), TranslateClassAToClassC },
                    { typeof(ClassB), TranslateClassBToClassD }
                };

        static Base2 TranslateClassAToClassC(Base1 old)
        {
            var oldClassA = old as ClassA;
            return new ClassC
                {
                    IntProperty = oldClassA.IntProperty
                };
        }

        static Base2 TranslateClassBToClassD(Base1 old)
        {
            var oldClassB = old as ClassB;
            return new ClassD
                {
                    StringProperty = oldClassB.StringProperty
                };
        }
    }

    abstract class Base1 { }

    class ClassA : Base1
    {
        public int IntProperty;
    }

    class ClassB : Base1
    {
        public string StringProperty;
    }

    abstract class Base2 { }

    class ClassC : Base2
    {
        public int IntProperty;
    }

    class ClassD : Base2
    {
        public string StringProperty;
    }
}

这可以完成我想要的所有内容,但Resharper会在我的翻译方法中抱怨可能的NullReferenceException(在“as”关键字之后)。我知道空引用是不可能的,因为我只使用我知道将正确转换的类型调用translate方法。我可以在演员表之后抛出一个空引用检查,但这是不必要的防御性编程,我试图尽可能保持干净。我也知道我可以忽略警告并继续前进,但我也认识到Resharper告诉我这是代码味道,我想知道正确的方法。

在一个理想的世界中,我可能会通过多态实现这一点,并让Base1实现一个名为ITranslatableToBase2的接口或类似的东西。但是在我的实际代码中,Base1来自POCO库并且不知道Base2,因此翻译器必须是它​​自己的多态对象。我尝试实现它,事实证明,虽然使用工厂模式比我在这里的字典模式稍微清晰,但是铸造问题仍然存在。

所以,我把它作为思想实验扔在这里。我已经筋疲力尽了几乎所有我能想到的东西,但也许还有一些我还没有想到的东西。在保持代码尽可能干净的同时,实现我正在尝试做的绝对最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

也许你可以使用适配器模式; 您可以拥有IClassC的接口,ClassC将实现此目的,然后:

public class ClassBToCAdapter : IClassC
{
     private ClassB adaptee;
     public ClassBToCAdapter(ClassB classB)
     {
        this.adaptee = classB
     }

     public int IntProperty
     {
        get { return adaptee.IntProperty; }
        set { adaptee.IntProperty = value; }
     }
}