Практическое руководство. Связывание обновлений модели с использованием транзакций
При определении расширения UML-конструкторов в Visual Studio Ultimate можно сгруппировать несколько изменений в одну транзакцию, которая называется связанный контекст отмены.
По умолчанию пользователь может отдельно отменить любое изменение, внесенное в модель с помощью кода.Например, если определяется команда меню, которая меняет местами названия двух UML-классов, пользователь может вызвать команду, а затем произвести отмену одной команды.Это действие позволяет отменить изменения только одного имени, оставляя неизменным другое имя и приводя модель в непреднамеренное состояние.
Во избежание этого с помощью кода можно выполнить ряд изменений в пределах транзакции.В результате для пользователя несколько изменений будут выглядеть как одно изменение.Последующее выполнение команды отмены позволяет отменить весь ряд изменений.
Дополнительное преимущество заключается в том, что с помощью кода можно отменить набор частично завершенных изменений, создав исключение или прервав транзакцию.
Группировка изменений в одну транзакцию
Убедитесь, что ссылки проекта включают следующую сборку .NET.
Microsoft.VisualStudio.Modeling.Sdk.11.0.dll
Внутри класса объявите импортированное свойство, имеющее тип ILinkedUndoContext.
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
...
class … {
[Import]
public ILinkedUndoContext LinkedUndoContext { get; set; }
В методе, изменяющем модель, заключите изменения в транзакцию.
using (ILinkedUndoTransaction transaction =
LinkedUndoContext.BeginTransaction("my updates"))
{
// code to update model elements or shapes goes here
transaction.Commit();
}
Обратите внимание на следующее.
Необходимо всегда включать Commit() в конце транзакции.Освобождение незафиксированной транзакции ведет к откату транзакции.Значит, восстанавливается состояние модели до начала транзакции.
Если создается исключение, которое не перехватывается внутри транзакции, производится откат транзакции.Очень часто блок using транзакции заключается в блок try…catch.
Разрешается вкладывать транзакции друг в друга.
Можно создать любое непустое имя для BeginTransaction().
Эти транзакции влияют только на хранилище моделей UML.Транзакции моделирования не влияют на переменные, внешние хранилища, такие как файлы и базы данных, схемы слоев, схемы последовательностей, созданные из кода, и модели кода.
Пример
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
using Microsoft.VisualStudio.Uml.Interfaces;
using Microsoft.VisualStudio.Uml.Classes;
using Microsoft.VisualStudio.Uml.Extensions;
using System.Linq;
using System.ComponentModel.Composition;
...
[Import]
public ILinkedUndoContext LinkedUndoContext { get; set; }
/// <summary>
/// Swap the names of the currently selected elements.
/// </summary>
public void Execute(IMenuCommand command)
{
var selectedShapes =
Context.CurrentDiagram.GetSelectedShapes<IClassifier>();
if (selectedShapes.Count() < 2) return;
IClassifier firstElement = selectedShapes.First().Element;
IClassifier lastElement = selectedShapes.Last().Element;
string firstName = firstElement.Name;
// Perform changes inside a transaction so that undo
// works as a single change.
using (ILinkedUndoTransaction transaction =
LinkedUndoContext.BeginTransaction("Swap names"))
{
firstElement.Name = lastElement.Name;
lastElement.Name = firstName;
transaction.Commit();
}
}
См. также
Основные понятия
Практическое руководство. Определение команды меню на схеме моделирования