То, что я пытаюсь выполнить sh
Я создал простой API, в который я пытаюсь наложить несколько различных шаблонов. В частности, команда, составной и прототип. Это Prototype, с которым у меня проблемы. Невероятно сложно продублировать этот тип и сломать все предыдущие ссылки. Причина, по которой я sh создаю прототип этого класса, состоит в том, что Команды должны запускаться только один раз, но если вам нужно sh, чтобы повторить функциональность, было бы легко дублировать Команды.
Где я работаю перебои
Интерфейс ICommand, который реализован во всех типах этой библиотеки, имеет метод ICommand Duplicate (). Единственный метод успешно прототипирует и проходит этот тест.
[Test]
public void Duplicated_Commands_Should_Be_Equivalent_But_Not_Identitical()
{
var sut = new ActionCommand(
callAction: _incrementTestValue,
undoAction: _decrementTestValue,
failureAction: _flagFailedTest);
var protoCommand = sut.Duplicate();
sut.Should().BeEquivalentTo(protoCommand); //Value equality.
sut.Should().NotBeSameAs(protoCommand); //Referential equality.
Однако, когда я пытаюсь ProtoType CompositeCommand, который является как списком ICommands, так и самой ICommand, согласно шаблону Composite, я сталкиваюсь с проблемой .
[Test]
public void Duplicated_Commands_Should_Yield_Same_Result()
{
int testVal = 0;
var sut = new CompositeCommand(
new ActionCommand(() => testVal++, () => testVal--, WriteLineOnFailure),
new ActionCommand(() => testVal++, () => testVal--, WriteLineOnFailure),
new ActionCommand(() => testVal++, () => testVal--, WriteLineOnFailure),
new ActionCommand(() => testVal++, () => testVal--, WriteLineOnFailure));
sut.Call();
testVal.Should().Be(sut.Count, "Each command increments this by one");
sut.Call();
testVal.Should().Be(sut.Count, "Assuming the previous Call() was successful the subsequent call should have exited early.");
sut.Success.Should().BeTrue();
var protoCommand = sut.Duplicate();
//THE LINE BELOW THIS FAILS
sut.Success.Should().BeTrue("Duplicating the sut should not mutate it in any way.");
//THE LINE ABOVE THIS FAILS
sut.Success.Should().BeFalse("Duplicated commands should have their Success set to false so that they can be executed.");
sut.Call();
protoCommand.Call();
testVal.Should().Be(sut.Count * 2, "We have 2 sets of identical commands.");
protoCommand.Call();
testVal.Should().Be(sut.Count * 2, "As with its singular counterpart, even duplicated commands should be Idempotent.");
}
Использование метода ICommands Call () обычно устанавливает для свойства Success значение true. Как вы можете видеть, это верно до вызова Duplicate, и CompositeCommand имеет аналогичный [Test], который подтверждает, что он эквивалентен, но не идентичен продукту его метода Duplicate.
При прохождении через него с помощью отладчика это показывает, что свойство Success sut помечается обратно в false, как только первая Duplicate ICommand назначается списку команд CompositeCommands. Он обнаруживает, что новая команда, для которой в конструкторе установлено значение «Успешное значение false», определенное по умолчанию, имеет свойство «Успешно», равное false, а CompositeCommand показывает «Успешное значение true» только в том случае, если все ее Команд успешно выполнены с помощью этого метода:
public bool Success
{
get
{
foreach (var command in Commands)
{
if (command.Success is false) return false;
}
return true;
}
set
{
foreach (var command in Commands)
{
command.Success = value;
}
}
}
То, что я до сих пор пробовал
Я пытался традиционное прототипирование с использованием сериализации и либо двоичной, либо xml сериализации. Делегаты, которые содержит этот тип, плохо реагируют на сериализацию, делегаты либо возвращают ноль с сериализацией xml, либо выдают исключение, когда делегат ссылается на значение из другого типа, такого как делегат Call, являющийся AnotherClassValue ++.
Я пытался создать конструктор Deep Copy, по отдельности вызвав метод Duplicate каждой отдельной ICommand и добавив продукты этого нового CompositeCommand. Это работает нормально, пока конструктор не разрешит, установив false для оригинала и прототипа на false, что заставляет меня поверить, что ссылки на ICommands действительно не нарушаются, несмотря на использование нового ключевого слова.
Любые предложения относительно того, что я мог бы исследовать, чтобы обнаружить источник проблемы? Я открыт для изменений в моем дизайне или любых тестах, которые кто-либо может предложить. **
Наконец, я рассказал всем здесь о самих методах Duplicate.
Command.Duplicate ()
public ICommand Duplicate()
{
var product = new ActionCommand(CallAction, UndoAction, FailureAction);
return product;
}
CompositeCommand.Duplicate ()
public ICommand Duplicate()
{
var commands = new ICommand[Commands.Count];
var currentCommands = Commands.ToArray();
for (var i = 0; i < commands.Length; i++)
{
commands[i] = currentCommands[i].Duplicate();
}
return new CompositeCommand(commands);
}