替换类型检查的条件链

时间:2011-01-24 22:43:57

标签: c#

我偶然发现了一些类似于以下内容的代码:

  if (myObject is MyClass1) 
     myOtherObject = new MyOtherClass1(myObject);
  else if (myObject  is MyClass2) 
     myOtherObject = new MyOtherClass2(myObject);
  else if (myObject  is MyClass3)
     myOtherObject = new MyOtherClass3(myObject);
  else if (myObject  is MyClass4)
     myOtherObject = new MyOtherClass4(myObject);
  else if (myObject  is MyClass5)
     myOtherObject = new MyOtherClass5(myObject);
  else if (myObject  is MyClass6) 
     // ...

我发现这有点难以维护,并希望用不那么麻烦的东西来代替它。我有什么选择?

到目前为止,我已经考虑过使用字典的表驱动方法,但我不确定这是否是最佳选择。

// Not even sure this is valid syntax.
foreach (myClass in classes)
   if myObject is myClass
      new classes[myClass](myObject);

还有其他想法吗?

更新

这里没有详细介绍这些类的基本结构:

MyBaseClass                              MyOtherBaseClass
  |                                        |
   -MyClass1                                -MyOtherClass1
  |                                        |
   -MyClass2                                -MyOtherClass2

MyBaseClass及其后代是我认为的持久数据传输对象。它们以特定于类的格式存储数据。

我最接近描述MyOtherBaseClass及其后代的是单向数据映射器[PoEAA],但它们也混合了一些业务逻辑。

数据库仅包含足够的信息来定位对象并跟踪其状态。

2 个答案:

答案 0 :(得分:5)

您是否可以考虑在generateOtherObject()MyClass1等基类中使用抽象方法MyClass2,在每个派生类中重写该方法以创建相关类型的新对象?

答案 1 :(得分:2)

另一个建议可能是使用构建器

下面的一个依赖于Dictionary,对于每种类型,它描述了为生成新实例而执行的构建操作(应该比if-else / switch语句更容易维护)。

如果MyOtherClass1,MyOtherClass2全部来自MyOtherBaseClass,则以下代码可以为您提供帮助:

    public class YourTypeBuilderBuilder
    {
        private readonly static IDictionary<Type, Func<object, MyOtherBaseClass>> builderMap = new Dictionary<Type, Func<object, MyOtherBaseClass>>();

        static YourTypeBuilderBuilder()
        {
            /* Here is described the specific behavior 
            of the building of the requested type */

            builderMap.Add(typeof(MyClass1), obj => new MyOtherClass1((MyClass1)obj));
            builderMap.Add(typeof(MyClass2), obj => new MyOtherClass2((MyClass2)obj));
            builderMap.Add(typeof(MyClass3), obj => new MyOtherClass3((MyClass3)obj));
        }

        public static MyOtherBaseClass Build<T>(T input)
        {
            Func<object, MyOtherBaseClass> typeBuilder;
            bool hasTypeBeenFound = builderMap.TryGetValue(typeof(T), out typeBuilder);

            if (!hasTypeBeenFound)
            {
                throw new ArgumentException(string.Format("'{0}' is not a valid parameter.", typeof(T)));
            }

            // Let's build the requested type
            MyOtherBaseClass obj = typeBuilder(input);

            return obj;
        }
    }

然后您的调用代码将变为

myOtherObject = YourTypeBuilder.Build(myObject);