Создание замещающих классов в пакетах
Glossary Item Box
Особенности создания замещающих классов
Работа с замещающими классами имеет следующие особенности:
- Для пакета c замещающим классом необходимо установить зависимость от пакета с замещаемым классом.
- Проектирование замещаемого и замещающего класса должно выполняться в соответствии с принципами наследования C#. В иерархии замещаемый класс является родителем, а замещающий класс — наследником.
- Все свойства и методы класса, которые необходимо заместить в других схемах, должны быть виртуальными. В замещающих классах эти свойства и методы переопределяются c ключевым словом override.
- При создании экземпляров замещающих классов необходимо соблюдать правила создания и применения конструкторов.
- До компиляции все свойства и методы, объявленные в замещающем классе и не объявленные как виртуальные в замещаемом классе, недоступны. Привязка и внедрение зависимостей типов выполняется open-source фреймворком внедрения зависимостей Ninject только во время выполнения.
- При создании замещаемых классов с параметризированными конструкторами необходимо соблюдать правила именования типов данных экземпляров аргументов, которые передаются в качестве параметров методу Get<T>.
Описание примера
В одном пользовательском пакете создать замещаемый класс и конфигурационный сервис. В другом пользовательском пакете создать замещающий класс. Продемонстрировать результат работы конфигурационного сервиса без замещения классов и с замещением классов.
Описание процесса разработки замещающего класса содержится в статье "Фабрика объектов замещающих классов".
Исходный код
Пакеты с реализацией примера можно скачать по ссылке.
Алгоритм реализации примера
1. Реализуйте замещаемый класс
В разделе [Конфигурация] ([Configuration]) пользовательского пакета на вкладке [Схемы] ([Schemas]) выполните действие [Добавить] —> [Исходный код] ([Add] —> [Source Code]). Процесс создания схемы типа [Исходный код] ([Source Code]) описан в статье "Создание схемы [Исходный код]".
Для создаваемой схемы объекта установите (рис. 1):
- [Заголовок] ([Title]) — "OriginalClassSourceSchema";
- [Название] ([Name]) — "UsrOriginalClassSourceSchema".
Рис. 1. — Настройка схемы объекта типа [Исходный код] ([Source Code])
Реализуйте замещаемый класс OriginalClass, содержащий метод GetAmount(int, int), для суммирования двух значений, переданных в качестве параметров. Полностью исходный код представлен ниже.
namespace Terrasoft.Configuration { public class OriginalClass { // Метод GetAmount() является виртуальным. Он может быть переопределен в наследниках и при этом имеет свою // реализацию. public virtual int GetAmount(int originalValue1, int originalValue2) { return originalValue1 + originalValue2; } } }
После внесения изменений сохраните и опубликуйте схему.
2. Реализуйте конфигурационный сервис
Для демонстрации работы метода GetAmount(int, int) замещаемого класса OriginalClass создайте конфигурационный сервис. Описание работы с конфигурационным сервисом содержится в блоке статей "Разработка и вызов конфигурационного сервиса".
В разделе [Конфигурация] ([Configuration]) пользовательского пакета на вкладке [Схемы] ([Schemas]) выполните действие [Добавить] —> [Исходный код] ([Add] —> [Source Code]). Процесс создания схемы типа [Исходный код] ([Source Code]) описан в статье "Создание схемы [Исходный код]".
Для создаваемой схемы объекта установите (рис. 2):
- [Заголовок] ([Title]) — "AmountService";
- [Название] ([Name]) — "UsrAmountService".
Рис. 2. — Настройка схемы объекта типа [Исходный код] ([Source Code])
Создайте класс сервиса AmountService, содержащий метод GetAmount(int, int), для суммирования двух значений, переданных в качестве параметров. Полностью исходный код с реализацией класса сервиса представлен ниже.
namespace Terrasoft.Configuration { using System.ServiceModel; using System.ServiceModel.Activation; using System.ServiceModel.Web; using Terrasoft.Core; using Terrasoft.Web.Common; [ServiceContract] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] public class AmountService : BaseService { [OperationContract] [WebGet(RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)] public string GetAmount(int value1, int value2) { /* // Создание экземпляра исходного класса через фабрику классов. var originalObject = Terrasoft.Core.Factories.ClassFactory.Get<OriginalClass>(); // Получение результата работы метода GetAmount(). В качестве параметров передаются значения из полей ввода страницы. int result = originalObject.GetAmount(value1, value2); // Возврат результата выполнения. return string.Format("Результат, полученный после применения метода замещаемого класса : {0}", result.ToString()); */ /* // Создание экземпляра замещающего класса через фабрику замещаемых объектов. // В качестве параметра метода фабрики передается экземпляр аргумента конструктора класса. var substObject = Terrasoft.Core.Factories.ClassFactory.Get<OriginalClass>(new Terrasoft.Core.Factories.ConstructorArgument("rateValue", 2)); // Получение результата работы метода GetAmount(). В качестве параметров передаются значения из полей ввода страницы. int result = substObject.GetAmount(value1, value2); // Отображение результата выполнения на странице. return string.Format("Результат, полученный после применения метода замещающего класса: {0}", result.ToString()); */ // Создание экземпляра замещающего класса через оператор new(). var substObjectByNew = new OriginalClass(); // Создание экземпляра замещающего класса через фабрику замещаемых объектов. var substObjectByFactory = Terrasoft.Core.Factories.ClassFactory.Get<OriginalClass>(new Terrasoft.Core.Factories.ConstructorArgument("rateValue", 2)); // Получение результата работы метода GetAmount(). Будет вызван метод исходного класса OriginalClass без замещения. int resultByNew = substObjectByNew.GetAmount(value1, value2); // Получение результата работы метода GetAmount(). Будет вызван метод класса SubstituteClass, который замещает OriginalClass. int resultByFactory = substObjectByFactory.GetAmount(value1, value2); // Отображение результата выполнения на странице. return string.Format("Результат, полученный без замещения классов: {0}; Результат, полученный с замещением классов: {1}", resultByNew.ToString(), resultByFactory.ToString()); } } }
После внесения изменений сохраните и опубликуйте схему.
3. Реализуйте замещающий класс
В зависимость пользовательского пакета с замещающим классом необходимо добавить пользовательский пакет с замещаемым классом.
В разделе [Конфигурация] ([Configuration]) пользовательского пакета на вкладке [Схемы] ([Schemas]) выполните действие [Добавить] —> [Исходный код] ([Add] —> [Source Code]). Процесс создания схемы типа [Исходный код] ([Source Code]) описан в статье "Создание схемы [Исходный код]".
Для создаваемой схемы объекта установите (рис. 8):
- [Заголовок] ([Title]) — "SubstituteClassSourceSchema";
- [Название] ([Name]) — "UsrSubstituteClassSourceSchema".
Рис. 3. — Настройка схемы объекта типа [Исходный код] ([Source Code])
Реализуйте замещающий класс SubstituteClass, содержащий метод GetAmount(int, int). Замещаемый метод выполняет суммирование двух значений, переданных ему в качестве параметра, и умножает полученную сумму на значение, переданное в свойстве Rate. Первичная инициализация свойства Rate будет выполняться в конструкторе замещающего класса. Полностью исходный код представлен ниже.
namespace Terrasoft.Configuration { [Terrasoft.Core.Factories.Override] public class SubstituteClass : OriginalClass { // Коэффициент. Значение свойства задается внутри класса. public int Rate { get; private set; } // В конструкторе выполняется первичная инициализация свойства Rate переданным значением. public SubstituteClass(int rateValue) { Rate = rateValue; } // Замещение родительского метода собственной реализацией. public override int GetAmount(int substValue1, int substValue2) { return (substValue1 + substValue2) * Rate; } } }
В результате выполнения примера в Creatio станет доступен новый конфигурационный сервис AmountService с конечной точкой GetAmount. При обращении к конечной точке сервиса, например, из браузера, в качестве параметров запроса необходимо передать значения value1 и value2.
Для демонстрации работы конфигурационного сервиса без замещения классов и с замещением классов введите следующую строку.
https://mycreatio.com/0/rest/AmountService/GetAmount?value1=25&value2=125
Результат работы метода GetAmount(int, int) представлен ниже.
{"GetAmountResult":"Результат, полученный без замещения классов: 150; Результат, полученный с замещением классов: 300"}