在我的代码中,我有一组对象,这些对象是不能使用新代码的类的实例。它们都需要转换为本地定义的相应类。我试图做一个干净的方法来确定实例所在的类的类型,并根据该类型调用适当的转换方法。但是,我似乎找不到像我想的那样干净利落的方法。这是我的代码。
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,因此翻译器必须是它自己的多态对象。我尝试实现它,事实证明,虽然使用工厂模式比我在这里的字典模式稍微清晰,但是铸造问题仍然存在。
所以,我把它作为思想实验扔在这里。我已经筋疲力尽了几乎所有我能想到的东西,但也许还有一些我还没有想到的东西。在保持代码尽可能干净的同时,实现我正在尝试做的绝对最佳方法是什么?
答案 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; }
}
}