Проблема
Я работаю с уже существующей библиотекой, исходный код которой у меня отсутствует. Эта библиотека представляет AST.
Я хочу скопировать части этого АСТ, но переименуйте ссылки на переменные в этом процессе. Поскольку может существовать AssignCommand-Object, который содержит объект Expression, я хочу иметь возможность копировать каждый объект со своей собственной функцией, поэтому я могу называть их рекурсивно. Однако, поскольку у меня нет доступа к коду библиотеки, я не могу добавить такой метод, как CopyAndRename(string prefix)
.
Таким образом, мой подход заключался в создании единственной функции Rename
с несколькими перегрузками. Таким образом, у меня будет семейство функций следующим образом:
public static Command Rename(Command cmd, string prefix)
public static AssignCommand Rename(AssignCommand cmd, string prefix)
public static AdditionExpressionRename(AdditionExpression expr, string prefix)
....
Теперь функция состоит из a List<Command>
, где AssignCommand
является подклассом Command
. Я предположил, что могу просто передать Command
в Rename
-функцию, и среда выполнения найдет наиболее конкретную. Однако это не так, и все команды передаются в Command Rename(Command cmd, string prefix)
. Почему это так? Есть ли способ делегировать вызов правильной функции без использования уродливых is
-операций?
Минимальный пример
Я нарушил эту проблему до следующего NUnit-Testcode
using NUnit.Framework;
public class TopClass{
public int retVal;
}
public class SubClassA : TopClass{ }
[TestFixture]
public class ThrowawayTest {
private TopClass Foo (TopClass x) {
x.retVal = 1;
return x;
}
private SubClassA Foo (SubClassA x) {
x.retVal = 2;
return x;
}
[Test]
public void OverloadTest(){
TopClass t = new TopClass();
TopClass t1 = new SubClassA();
SubClassA s1 = new SubClassA();
t = Foo (t);
t1 = Foo (t1);
s1 = Foo (s1);
Assert.AreEqual(1, t.retVal);
Assert.AreEqual(2, s1.retVal);
Assert.AreEqual(2, t1.retVal);
}
}
Итак, мой вопрос сводится к следующему: "Как можно проверить тест выше в элегантном, полиморфном, объектно-ориентированном виде, не прибегая к is
-checks?"
Методы расширения
Я также пробовал использовать методы расширения следующим образом. Это не решило проблему, поскольку они являются просто синтаксическим сахаром для подхода выше:
using NUnit.Framework;
using ExtensionMethods;
public class TopClass{
public int retVal;
}
public class SubClassA : TopClass{ }
[TestFixture]
public class ThrowawayTest {
private TopClass Foo (TopClass x) {
x.retVal = 1;
return x;
}
private SubClassA Foo (SubClassA x) {
x.retVal = 2;
return x;
}
[Test]
public void OverloadTest(){
TopClass t = new TopClass();
TopClass t1 = new SubClassA();
SubClassA s1 = new SubClassA();
t.Foo(); s1.Foo(); t1.Foo();
Assert.AreEqual(1, t.retVal);
Assert.AreEqual(2, s1.retVal);
Assert.AreEqual(2, t1.retVal);
}
}
namespace ExtensionMethods{
public static class Extensions {
public static void Foo (this TopClass x) {
x.retVal = 1;
}
public static void Foo (this SubClassA x) {
x.retVal = 2;
}
}
}