2014-02-05

Расширения DocsVision и объектная модель

В DocsVision есть возможность написаний расширений навигатора и серверных расширений.
Также можно написать свое независимое приложение, которое будет подключаться к базе DocsVision и работать с объектами.
Плюс мы еще можем создавать веб-скрипты ASPX (веб-версию). Они будут доступны по адресу http://DVSERVER/DocsVision/MyScript.aspx.
Аналогично пишутся скрипты в бизнес-процессах, если возможностей шлюзов (DVGate) недостаточно. Планирую рассказать поподробней про бизнес-процессы в одной из следующих статей.
Еще к возможностям расширениям я бы отнес поддержку собственных элементов управления для разметок. Эта возможность изучена мной поверхностно. Может, будет такая задача и тогда напишу в блог подробности.
Вкратце рассмотрим подробнее перечисленные выше возможности.

Сессия и контекст


Для того, чтобы работать с объектной моделью DocsVision у нас должна быть инициализирована сессия (UserSession) и контекст (ObjectContext).
Класс расширения навигатора наследуется от NavExtension. В нем пользовательская сессия уже существует, остается лишь используя ее создать контекст.
В остальных случаях (серверное расширение, standalone-приложение, скрипт бизнес-процесса, веб-версия) нам предварительно необходимо подключаться к StorageServer и создавать сессию.

Контекст:

private ObjectContext _objectContext = null;
private ObjectContext objectContext
{
 get
 {
  if (this._objectContext == null)
  {
   ServiceContainer sessionContainer = new ServiceContainer();
   sessionContainer.AddService(
    typeof(UserSession),
    //Type.GetType("DocsVision.Platform.ObjectManager.UserSession, DocsVision.Platform.ObjectManager, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519"),
    this.Session
   );
   this._objectContext = new ObjectContext(sessionContainer);
   IObjectMapperFactoryRegistry mapperFactoryRegistry = this._objectContext.GetService<IObjectMapperFactoryRegistry>();
   mapperFactoryRegistry.RegisterFactory(typeof(SystemCardsMapperFactory));
   mapperFactoryRegistry.RegisterFactory(typeof(BackOfficeMapperFactory));
   IServiceFactoryRegistry serviceFactoryRegistry = this._objectContext.GetService<IServiceFactoryRegistry>();
   serviceFactoryRegistry.RegisterFactory(typeof(BackOfficeServiceFactory));
   serviceFactoryRegistry.RegisterFactory(typeof(SystemCardsServiceFactory));
   this._objectContext.AddService<IPersistentStore>(DocsVisionObjectFactory.CreatePersistentStore(new SessionProvider(this.Session), null));
   IMetadataProvider metadataProvider = DocsVisionObjectFactory.CreateMetadataProvider(this.Session);
   this._objectContext.AddService<IMetadataManager>(DocsVisionObjectFactory.CreateMetadataManager(metadataProvider, this.Session));
   this._objectContext.AddService<IMetadataProvider>(metadataProvider);
  }
  return this._objectContext;
 }
 set
 {
  if (this._objectContext != null)
  {
   this._objectContext.Dispose();
  }
  this._objectContext = value;
 }
}

Сессия:

// ConnectionAddress ~ http://localhost/DocsVision/StorageServer/StorageServerService.asmx
// тут указываем строку подключения к StorageServer:
private String connectionString = "";
private UserSession _session = null;
private UserSession Session
{
 get
 {
  if (this._session == null)
  {
   // также возможно подключение с использованием ConnectionAddress
   SessionManager sessionManager = SessionManager.CreateInstance(this.connectionString);
   // connectionString
   //sessionManager.Connect(this.connectionString);
   // connectionAddress
   //sessionManager.Connect(this.connectionAddress, null);
   this._session = sessionManager.CreateSession();
  }
  return this._session;
 }
 set
 {
  if (this._session != null)
  {
   this._session.Close();
  }
  this._session = value;
 }
}

После получения контекста и сессии можно полноценно работать с объектами DocsVision.

Расширение навигатора


Расширять можно ленту команд (появляется отдельная вкладка "Расширения"), контекстное меню карточек, папки, окно свойств карточки и др. Подробней о возможностях расширения написано в документации.
Чтобы создать расширение необходимо создать библиотеку классов dll и унаследовать класс от NavExtension, переопределить методы описывающие расширение и его команды. Дополнительно нужно подготовить карточку в CardManager и загрузить ее в базу и связать по GUID с библиотекой классов. Библиотека должна быть видима для COM и ее нужно зарегистрировать с помощью утилиты RegAsm из .NET-фреймворка.

Серверное расширение


Служит для создания любых команд отрабатывающих на серверной стороне.
Во-первых создаем библиотеку классов dll и наследуем класс от StorageServerExtension. Затем регистрируем расширение в реестре (HKEY_LOCAL_MACHINE\SOFTWARE\DocsVision\Platform\5.0\Server\Extensions). Каждый раз после компиляции dll нужно обновлять кеш сборок системы с помощью утилиты gacutil.
Доступные вовне методы расширения в классе помечаются атрибутами "[ExtensionMethod]".

Пример вызова:

ExtensionMethod mymethod = this.Session.ExtensionManager.GetExtensionMethod("LibraryServerExtension", "MyMethod");
mymethod.Parameters.AddNew("id", ParameterValueType.Guid, Guid.Empty);
String id = mymethod.Execute().ToString();

Standalone-приложение


Тут все просто: подключаемся к StorageServer, инициализируем сессию и контекст и работаем с объектами DocsVision.

Веб-версия (ASPX)


В интернет-браузере все скрипты из папки C:\Program Files (x86)\Docsvision\Platform\5.0\Site доступны по адресам вида http://DVSERVER/DocsVision/*.aspx.
Была такая задача: веб-версия некоторых видов документов. Посмотрев на существующие примеры aspx-скриптов из папки Site опытным путем было выяснено, что в них можно написать все те же скрипты, что и в отдельном расширении. Инициализированная сессия не была найдена в контексте страницы, пришлось создавать по аналогии со standalone-приложением.

Пример работы с документом:

<%@ page language="C#" autoeventwireup="true" inherits="DocsVision.Platform.Web.InfoPage, App_Web_infopage.aspx.cdcab7d2" masterpagefile="~/Default.master" theme="DefaultTheme" %>
<%@ OutputCache Duration="1800" VaryByParam="LangName" %>
<%@ Register Assembly="DocsVision.Platform.Web" Namespace="DocsVision.Platform.Web.UI"
 TagPrefix="dv" %>
 
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.ComponentModel.Design" %>

<!-- добавляем сборки, регистрируем пространства имен -->
<%@ Register Assembly="DocsVision.BackOffice.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.BackOffice.ObjectModel"
 TagPrefix="dv" %>
<%@ Register Assembly="DocsVision.BackOffice.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.BackOffice.ObjectModel.Mapping"
 TagPrefix="dv" %>
<%@ Register Assembly="DocsVision.BackOffice.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.BackOffice.ObjectModel.Services"
 TagPrefix="dv" %>
<%@ Register Assembly="DocsVision.Platform, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.Platform.Data.Metadata"
 TagPrefix="dv" %>
<%@ Register Assembly="DocsVision.Platform.ObjectManager, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.Platform.ObjectManager"
 TagPrefix="dv" %>
<%@ Register Assembly="DocsVision.Platform.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.Platform.ObjectModel"
 TagPrefix="dv" %>
<%@ Register Assembly="DocsVision.Platform.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.Platform.ObjectModel.Mapping"
 TagPrefix="dv" %>
<%@ Register Assembly="DocsVision.Platform.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.Platform.ObjectModel.Persistence"
 TagPrefix="dv" %>
<%@ Register Assembly="DocsVision.Platform.SystemCards.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.Platform.SystemCards.ObjectModel.Mapping"
 TagPrefix="dv" %>
<%@ Register Assembly="DocsVision.Platform.SystemCards.ObjectModel, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519" Namespace="DocsVision.Platform.SystemCards.ObjectModel.Services"
 TagPrefix="dv" %>

<asp:Content ID="Content1" ContentPlaceHolderID="HeadContentPlaceHolder" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="BodyContentPlaceHolder" runat="Server">
<div>
<%

// подключаемся к серверу и создаем сессию
SessionManager sessionManager = SessionManager.CreateInstance();
sessionManager.Connect("http://DVSERVER/DocsVision/StorageServer/StorageServerService.asmx", null);
UserSession session = sessionManager.CreateSession();

// создаем контекст
ServiceContainer sessionContainer = new ServiceContainer();
sessionContainer.AddService(Type.GetType("DocsVision.Platform.ObjectManager.UserSession, DocsVision.Platform.ObjectManager, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7148afe997f90519"), session);
ObjectContext objectContext = new ObjectContext(sessionContainer);
IObjectMapperFactoryRegistry mapperFactoryRegistry = objectContext.GetService<IObjectMapperFactoryRegistry>();
mapperFactoryRegistry.RegisterFactory(typeof(BackOfficeMapperFactory));
IServiceFactoryRegistry serviceFactoryRegistry = objectContext.GetService<IServiceFactoryRegistry>();
serviceFactoryRegistry.RegisterFactory(typeof(BackOfficeServiceFactory));
objectContext.AddService(DocsVisionObjectFactory.CreatePersistentStore(new SessionProvider(session), null));
IMetadataProvider metadataProvider = DocsVisionObjectFactory.CreateMetadataProvider(session);
objectContext.AddService(DocsVisionObjectFactory.CreateMetadataManager(metadataProvider, session));
objectContext.AddService(metadataProvider);

// можем работать с карточками
Document doc = objectContext.GetObject<Document>(new Guid("{DB5DE01D-3571-E311-A92F-00093D145B31}"));
Response.Write(doc.MainInfo.Name);

%>
</div>
</asp:Content>

Скрипты в бизнес-процессах


Аналогично, нам нужна сессия и контекст. Дополнительно в скриптах бизнес-процессов нам доступны шлюзы к простым типам, файловой системе и DocsVision.