Пишем свое расширение для Редактора модели клиента СК-11
Статья-пример базовой реализации собственного расширения для клиента СК-11 для тех, кого ограничивает штатный функционал клиента СК-11.
Например, нужен свой спец. редактор для определенного класса или нужно автоматизировать какую-либо задачу, для которой штатных функций редактора скриптов недостаточно.
Создание и настройка проекта в Visual Studio
- В VisualStudio создать новый проект типа "Библиотека классов (.NET Framework)"
- Указать платформу: ".NET Framework 4.8"

- В настройках проекта указать Целевую платформу x64 для всех конфигураций сборки

Для компиляции расширения необходимо подключить следующие библиотеки:
Чтобы добавить ссылки на библиотеки нужно в дереве решения выбрать пункт
Ссылки->ПКМ->Добавить ссылку...

из GAC нужно добавить сборки:
- PresentationCore
- PresentationFramework
из
<ПАПКА УСТАНОВКИ VISUAL STUDIO>\Common7\IDE\Extensions\Microsoft\LiveShare\Agent\илиC:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\добавить сборку:- System.ComponentModel.Composition.dll
из
папки с клиентом СК-11:- Monitel.Mal.dll
- Monitel.UI.Infrastructure.dll
Результирующий вид дерева решения должен быть примерно такой:

Создание точки входа и объявление необходимых параметров для дальнейшего импорта в СК-11
Для подключения своего расширения к клиенту СК-11 необходимо выполнить ряд требований к ранее созданному классу:
- Класс должен реализовывать интерфейс
IExtension(из пространства имен Monitel.UI.Infrastructure.Extensions) - Описывать определенные значения метаданных для импорта в клиент СК-11
Выполнение требования 1:

Выполнение требования 2:

Итоговый код Class1.cs:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using Monitel.UI.Infrastructure.Services;
using Monitel.UI.Infrastructure.Extensions;
using System.ComponentModel.Composition;
namespace TestExtension
{
[Export(typeof(IExtension))]
[ExportMetadata("Name", "Тестовое расширение для СК-11")]
[ExportMetadata("Description", "Расширение для Редактора модели СК-11")]
[ExportMetadata("GroupName", "Расширения Вовк В.И.")]
[ExportMetadata("ShowInToolBar", true)]
[ExportMetadata("ShowInMenu", true)]
[ExportMetadata("ExecutionMode", ExtensionExecutionMode.Control)]
[ExportMetadata("SupportedModels", new string[] { "All" })]
[ExportMetadata("MalUniversalAccess", true)]
[ExportMetadata("LocaleId", "VovkVI.TestExtension")]
public class Class1: IExtension
{
public BitmapSource Icon => null;
public MenuItem MenuItem => null;
public Control ToolBarItem => null;
public Control CreateControl(IServiceManager services)
{
return new TestControl(services);
}
public bool ShowDialog(Window owner, IServiceManager services)
{
return false;
}
}
}где:
реализация IExtension:
- Icon - определяет иконку расширения, которая будет отображена в выпадающем меню и на панели инструментов клиента СК-11
- MenuItem - позволяет создать свое меню выпадающем меню клиента СК-11 (не просто кнопка, а, например, вложенные папки и т.д.)
- ToolBarItem - позволяет создать свое меню на панели инструментов клиента СК-11
- CreateControl - данный метод выполняется только если
ExportMetadata("ExecutionMode", ...)имеет значение равноеExtensionExecutionMode.Control - ShowDialog - данный метод выполняется только если
ExportMetadata("ExecutionMode", ...)имеет значение равноеExtensionExecutionMode.Dialog
значения атрибутов Export:
- Name - Имя расширения. Отображается в выпадающем меню и на панели инструментов, если не задана иконка расширения;
- Description - Описание расширения. Отображается при наведении курсора мыши на иконку расширения на панели инструментов;
- GroupName - Произвольное значение. Предположительно участвует в какой-то внутренней логике СК-1;
- ShowInToolBar - Определяет показывать ли расширение на панели инструментов;
- ShowInMenu - Определяет показывать ли расширение в выпадающем меню;
- ExecutionMode - Определяет режим работы расширения. Либо как встраеваемый элемент управления, либо как отдельное окно, если задано ExtensionExecutionMode.Dialog;
- SupportedModels - Определяет с какими версиями канонической модели работать. Можно указать конкретную версию, например: CIM16;
- MalUniversalAccess - ХЗ зачем, возможно дает особый вид доступа к объектной модели, но это не точно 😄
- LocaleId - Произвольное значение. Какой-то идентификатор (расширения либо для определения локализации), нужен для внутренней логики СК-11.
Создание пользовательского элемента управления для отрисовки графического интерфейса
Для добавления графического интерфейса к расширению создадим компонент пользовательского элемента управления и назовем его как TestControl.xaml:

Добавим разметку. Расширение будет показывать сообщение с UIDом выбранного в дереве объекта

Итоговый код файла разметки TestControl.xaml:
<UserControl x:Class="TestExtension.TestControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TestExtension"
mc:Ignorable="d"
Background="White"
d:DesignHeight="300" d:DesignWidth="400">
<StackPanel Width="200" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5">
<TextBlock Text="Выберите объект в дереве и нажмите на кнопку для получения информации об объекте" TextWrapping="WrapWithOverflow" TextAlignment="Center"/>
<Button x:Name="btnMsgInfo" Content="Информация об объекте" Height="32" Margin="10" Padding="5" FontSize="10"/>
</StackPanel>
</UserControl>Добавим логику. Для отображения заголовка расширения во вкладке нужно, чтобы класс TestControl реализовывал интерфейс IExtensionControl. ВАЖНО: чтобы конструктор класса TestControl принимал аргументом объект класса IServiceManager. Это нужно для доступа с ModelImage и другим сервисам редактора модели:

Итоговый код файла TestControl.xaml.cs:
using System;
using System.Windows;
using System.Windows.Controls;
using Monitel.UI.Infrastructure.Services;
using Monitel.UI.Infrastructure.Extensions;
namespace TestExtension
{
public partial class TestControl : UserControl, IExtensionControl
{
public string Header => "Тестовое расширение";
public Control Toolbox => null;
public bool CanClose() => true;
public event EventHandler<EventArgs> HeaderChanged;
public readonly IServiceManager _Services = null;
public TestControl(IServiceManager services = null)
{
InitializeComponent();
this._Services = services;
this.btnMsgInfo.Click += btnClick;
}
private void btnClick(object sender, RoutedEventArgs e)
{
if (this._Services is null) return;
var selObj = _Services.Navigation.SelectedObject;
if (selObj is null) return;
MessageBox.Show($"UID выбранного объекта: {selObj.Uid}", "Информация", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}Сборка расширения
Собираем решение: "Сборка" → "Собрать решение" или Ctrl + Shift + B.
Подключение расширения к клиенту СК-11

Для подключения расширения к клиенту СК-11 нужно:
Перейти в папку с клиентом СК-11, например:
batchC:\Program Files\Monitel\CK-11\ClientПереместить в папку с клиентом СК-11 ранее собраный файл расширения TestExtension.dll
Создать *.xml файл с названием MNExtensions.Custom.xml название ОБЯЗАТЕЛЬНО должно быть именно таким.
MNExtensions.Custom.xml
xml<?xml version="1.0" encoding="utf-8" ?> <Extensions> <Extension FileName="TestExtension.dll" /> </Extensions>Всё, можно запускать редактор модели СК-11 😄
Результат работы расширения:



Разные полезности:
- Чтобы получить доступ к объекту выбранному в дереве:
var selObj = services.Navigation.SelectedObject; // возвращает IMalObject- Чтобы получить доступ к объектной модели текущего контекста используем:
var MImage = services.DataSource.MainModelImage; // возвращает IModelImage- Чтобы получить доступ к объектной модели контекста AppData используем:
var ADImage = services.DataSource.AppDataModelImage; // возвращает IModelImage- Чтобы вывести сообщение в протокол используем:
services.Journal.WriteMessage(new JournalMessage(...));