"Простой" сценарий

"Простой" сценарий

В прошлый раз я рассказал о том, как создать независимое приложение, использующее службы Капеллы. Это интересная задача, но основная часть работы с Капеллой связана не с написанием отдельных приложений, а с написанием форм, работающих непосредственно в клиентской части (АРМ) и сценариев, запускаемых сервером сценариев (workflow service). Сегодня я расскажу, как же это делается.

Сегодня мы займемся разработкой отдельного проекта (но уже внутри Капеллы) с одним очень простым и довольно классическим сценарием (Hello, User). Сценарий будет содержать две формы. На первой форме мы спросим имя пользователя, а на второй выведем приветствие для него. Мы пока не будем работать с базой данных – этим займемся в следующий раз.

Подготовка решения

Мы начинаем разработку нового проекта под Капеллу 3.5, и начать нужно с создания нового решения. Решение должно уже содержать проект CoreBinaries, о котором я рассказывал здесь

Если у вас уже есть решение CallSimulator, можно просто скопировать раздел, в котором находится это решение, называть новый раздел и находящийся в нем .sln-файл именем проекта (я назову его BlogProject) и удалить все подразделы, кроме CoreBinaries. Потом открыть этот .sln в Visual Studio и удалить все старые проекты, которые не смогли подгрузиться. У нас в решении останется один только CoreBinaries, и мы начинаем новый проект «с чистого листа». Решение в Visual Studio должно теперь выглядеть так, как показано на рисунке.



Создание проектов

Каждое решение для Капеллы обязательно имеет два проекта – это проект форм и проект сценариев. Обычно они называются как «ИмяРешения.Forms» (в нашем случае BlogProject.Forms) и «ИмяРешения.Workflow» (в нашем случае BlogProject.Workflow). Создадим эти проекты в Visual Studio, нажимая правой кнопкой на нашем решении и выбирая «Добавить / Создать проект». При добавлении проектов нужно выбрать .NET Framework 3.5 в качестве целевой версии.

Для создания проекта форм выбираем шаблон Visual C# / Windows / Библиотека пользовательских элементов управления WPF. Не забываем назвать проект «BlogProject.Forms». Для создания проекта сценариев выбираем шаблон Visual C# / Workflow / Библиотека последовательного рабочего процесса и называем проект BlogProject.Workflow. После того, как проекты будут созданы, удаляем из них файлы UserControl1.xaml и Workflow1.cs.

Настройка проектов

Чтобы Капелла смогла «увидеть» наши проекты, нужно расположить их определенным образом. Сборки с формами должны располагаться в разделе, названном именем проекта, и этот раздел должен быть расположен там же, где находится сервер безопасности (Security Service).

Раздел со сборками сценариев должен быть доступен с сервера сценариев (Workflow Service). Расположение этого раздела конфигурируется, но обычно в разделе сервера сценариев для этого создается раздел Applications, в котором создается подраздел с именем приложения, и сборки сценариев помещаются в этот подраздел.

В предыдущих двух абзацах под проектом понимается не проект Visual Studio, а клиентский проект. В терминах Visual Studio это само решение. Имя проекта будет фигурировать еще в нескольких местах, в том числе и при настройке хранилища (чем мы займемся в следующий раз).

Итак, в нашем решении все серверы Капеллы находятся после построения в CoreBinaries/bin/Debug (или CoreBinaries/bin/Release), откуда они и запускаются нами с помощью скрипта startup.cmd. Поэтому нам требуется зайти в свойства созданных нами проектов форм и сценариев, перейти на страницу «Построение» и в поле «Путь вывода» указать:

- BlogProject.Forms, конфигурация Debug:
..\CoreBinaries\bin\Debug\BlogProject\
- BlogProject.Forms, конфигурация Release:
..\CoreBinaries\bin\Release\BlogProject\
- BlogProject.Workflow, конфигурация Debug:
..\CoreBinaries\bin\Debug\Applications\BlogProject\
- BlogProject.Workflow, конфигурация Release:
..\CoreBinaries\bin\Release\Applications\BlogProject\


Теперь добавляем ссылки на сборки Капеллы. При добавлении ссылок выбираем «Обзор» и переходим в раздел CoreBinaries\bin\Debug (проект CoreBinaries должен быть предварительно построен, чтобы сборки оказались там).

Для BlogProject.Forms добавляем ссылки на:

- C3.dll
- C3.AgentDesktop.dll
- C3.Application.dll
- C3.Application.Forms.dll
- C3.Communication.dll
- C3.Data.dll
- C3.Security.dll
- C3.Workflow.dll


Для BlogProject.Workflow добавляем ссылки на:

- C3.dll
- C3.Data.dll
- C3.Security.dll
- C3.Workflow.dll
- C3.Workflow.Activity.dll
- C3.Workflow.Application.dll


Теперь требуется включить ссылки на клиентские файлы .config в созданные нами проекты. Для этого нажмите правой кнопкой на проекте BlogProject.Forms, выберите «Добавить / Существующий элемент», перейдите в раздел CoreBinaries, отобразите файлы *.config, выделите следующие файлы:

- AuthorizationProvider.config
- CommunicationProvider.config
- DataProvider.config
- WorkflowProvider.config


Выделив эти файлы, нажмите стрелку справа от кнопки «Добавить» и выберите «Добавить как связь». Выделите добавленные файлы на панели обозревателя решений, и в их свойствах задайте для параметра «Копировать в выходной каталог» значение «Копировать, если новее». Теперь снимите выделение с файла WorkflowProvider.config (остальные три файла должны быть выделены) и перетащите их в BlogProject.Workflow, держа нажатой клавишу Ctrl.

Последним этапом подготовки файлов проектов будет создание файлов конфигурации. Создайте в проекте BlogProject.Forms файл App.config и скопируйте в него такое содержимое:

Код
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="c3.configuration" type="C3.Application.Configuration.ApplicationSectionGroup, C3.Application">
   <section name="implementation" type="C3.Activation.ImplementationSection, C3"/>
   <section name="application" type="C3.Application.Configuration.ApplicationSection, C3.Application"/>
   <section name="applicationtypes" type="C3.Application.Configuration.ApplicationTypesSection, C3.Application"/>
   <section name="libs" type="C3.Application.Configuration.LibsSection, C3.Application"/>
   <section name="forms" type="C3.Application.Configuration.FormsSection, C3.Application"/>
    </sectionGroup>
  </configSections>
  <c3.configuration xmlns="schemas://c3.configuration/Desktop/Application/">
    [i]
   <add interface="C3.Security.IAuthorizationProvider, C3" type="C3.Security.AuthorizationProvider, C3.Security"/>
   <add interface="C3.Communication.ICommunicationProvider, C3" type="C3.Communication.CommunicationProvider, C3.Communication"/>
   <add interface="C3.Application.IApplicationHostManager, C3.Application" type="C3.AgentDesktop.ApplicationHostManager, C3.AgentDesktop"/>
   <add interface="C3.Data.IDataProvider, C3" type="C3.Data.Proxy.ProxyDataProvider, C3.Data"/>
   <add interface="C3.Workflow.IWorkflowProvider, C3" type="C3.Workflow.WorkflowProvider, C3.Workflow"/>
   <add interface="C3.Application.IScreenCaptureProvider, C3.Application" type="C3.Application.ScreenCapture.ScreenCaptureProvider, C3.Application.ScreenCapture"/>
   <add interface="C3.Application.Forms.ICallControlProvider, C3.Application.Forms" type="C3.Application.Forms.BaseCallControlProvider, C3.Application.Forms"/>
   <add interface="C3.Application.Forms.Controls.EntityCard.IDataUpdater, C3.Application.Forms" type="C3.Application.Forms.Controls.EmptyDataUpdater, C3.Application.Forms" name="IDataUpdaterImpl"/>
    [/i]
    <applicationtypes>
   <add name="Workflow" type="C3.Application.Forms.WorkflowManager, C3.Application.Forms"/>
   <add name="Code" type="C3.Application.Forms.CodeManager, C3.Application.Forms"/>
   <add name="Win32" type="C3.Application.Win32.Win32HostFactory, C3.Application.Win32"/>
   <add name="Web" type="C3.Application.Web.WebHostFactory, C3.Application.Web"/>
    </applicationtypes>
    <application name="BlogProject" displayName="Капелла">
    </application>
    <forms>
   <add lib="BlogProject.Forms"/>
    </forms>
    <libs>
    </libs>
  </c3.configuration>
</configuration>
Теперь создайте файл App.config в проекте BlogProject.Workflow и скопируйте в него следующее:

Код
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="c3.configuration">
   <section name="implementation" type="C3.Activation.ImplementationSection, C3"/>
    </sectionGroup>
    <sectionGroup name="c3.workflow" type="C3.Workflow.Application.Configuration.WorkflowSectionGroup, C3.Workflow.Application">
   <section name="runtime" type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
   <section name="application" type="C3.Workflow.Application.Configuration.ApplicationSection, C3.Workflow.Application"/>
    </sectionGroup>
  </configSections>
  <c3.configuration>
    [i]
   <add interface="C3.Security.IAuthorizationProvider, C3" type="C3.Security.AuthorizationProvider, C3.Security"/>
   <add interface="C3.Communication.ICommunicationProvider, C3" type="C3.Communication.CommunicationProvider, C3.Communication"/>
   <add interface="C3.Application.IApplicationHostManager, C3.Application" type="C3.AgentDesktop.ApplicationHostManager, C3.AgentDesktop"/>
   <add interface="C3.Data.IDataProvider, C3" type="C3.Data.InstancingDataProvider, C3.Data"/>
   <add interface="C3.Workflow.IWorkflowProvider, C3" type="C3.Workflow.WorkflowProvider, C3.Workflow"/>
    [/i]
  </c3.configuration>
  <c3.workflow xmlns="schemas://c3.configuration/workflow/">
    <runtime Name="Hosting">
   <CommonParameters/>
   <Services>
     <add type="System.Workflow.Runtime.Hosting.DefaultWorkflowSchedulerService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" maxSimultaneousWorkflows="10"/>
   </Services>
    </runtime>
    <application>
    </application>
  </c3.workflow>
  <startup>
    <supportedRuntime version="v2.0.50727"/>
  </startup>
</configuration>
Настройка CoreBinaries

Теперь нужно внести изменения в некоторые конфигурационные файлы, находящиеся в проекте CoreBinaries.

Откройте файл C3.Workflow.Service.WindowsService.exe.config. Найдите в этом файле элемент <c3.workflow.host>. Если он уже содержит элемент <applicationHost>, удалите его, а затем добавьте новое значение для <applicationHost>:
Код
<applicationHost>
  <applications>
    <add name="BlogProject"
      path="Applications\BlogProject"
      confFileName="BlogProject.Workflow.dll.config"/>
  </applications>
  <securityManager authSystemName="C3" userName="WorkflowServiceSima" password="Capella"/>
</applicationHost>
Мы задали раздел сборок сценариев нашего проекта относительно сервера сценариев, о чем я говорил выше. Теперь укажем параметры нашего проекта для C3.Starter.exe. Для этого откройте файл C3.Starter.exe.config, в котором найдите элемент <applications>, расположенный внутри <c3.starter>. Можно удалить все перечисленные там приложения (проекты), после чего добавить наше:

Код
<add name="BlogProject" appConfigName="BlogProject.Forms.dll.config">
  <autologon authSystem="C3" userName="comtest1" password="simasima" phone="101"/>
</add>
Теперь можно назначить проект BlogProject.Forms запускаемым проектом, открыть его свойства, перейти на страницу «Отладка», указать действие при запуске «Запуск внешней программы», выбрать в качестве внешней программы ..\CoreBinaries\bin\Debug\C3.Starter.exe (для конфигурации Release измените путь соответственно). В качестве аргументов командной строки укажите «BlogProject» без кавычек – это позволит приложению C3.Starter.exe выбрать нужное приложение при запуске, если в C3.Starter.exe.config указано несколько приложений.

Теперь запустим серверы Капеллы с помощью startup.cmd из CoreBinaries\bin\Debug. После успешного запуска серверов можно запустить наше решение. Запуск должен пройти успешно, и после загрузки должно появиться пустое окно Капеллы, изображенное на рисунке.



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

Теперь создадим простой сценарий с двумя формами, о котором я писал вначале, и заставим его запускаться при запуске Капеллы.

Создаем формы

Формы в Капелле – это элементы управления, обычно наследуемые от UserControl. Сценарии обращаются к формам по имени, являющемуся именем класса формы, поэтому классам форм нужно давать осмысленные имена.

Создадим первую форму в проекте BlogProject.Forms. Для этого нажмем на этом проекте правой кнопкой и выберем «Добавить / Пользовательский элемент управления». В поле с именем укажем «HelloInput.xaml» и нажмем кнопку «Добавить».

Как я и обещал, пока мы не будем работать с базой данных (универсальным хранилищем) и ограничимся пересылкой между формой и сценарием только строки (System.String). Чтобы можно было ссылаться на тип string, добавим определение соответствующего xmlns в наш xaml:
Код
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Кроме того, нам потребуется пространство имен forms, содержащее элементы управления Капеллы:
Код
xmlns:forms="clr-namespace:C3.Application.Forms.Controls;assembly=C3.Application.Forms"
Параметры между сценариями и формами передаются двумя способами, мы пока будем использовать один из них – через ObjectDataProvider. Для этого определим ресурсы нашей формы следующим образом:
Код
[u]
    <ObjectDataProvider x:Key="UserName" ObjectType="{x:Type sys:String}" />
[/u]
Теперь зададим содержимое формы:
Код
<Grid Width="300">
    <Label Target="{Binding ElementName=UserName}" VerticalAlignment="Top">Ваше _имя:</Label>
     <TextBox x:Name="UserName" VerticalAlignment="Top" Margin="4,32,4,0" Text="{Binding Path=ObjectInstance, BindsDirectlyToSource=True, Source={StaticResource UserName}}" />
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="4,60,4,0">
     <forms:FormActionButton Action="Next" Margin="4,0,0,0" Padding="12,2">_Далее</forms:FormActionButton>
     <forms:FormActionButton Action="Cancel" Margin="4,0,0,0" Padding="12,2">_Отмена</forms:FormActionButton>
    </StackPanel>
</Grid>
Как вы можете видеть, наша форма содержит TextBox, в котором мы просим пользователя ввести его имя. Введенное имя будет записано в ресурс UserName, который является ObjectDataProvider-ом. Это значение уйдет впоследствии в сценарий.

Также форма имеет две особые кнопки – FormActionButton. Когда пользователь нажимает на такую кнопку, команда из свойства Action передается в сценарий, а форма закрывается.

В привязке значения Text для TextBox мы использовали хитрость, позволяющую сделать двухстороннюю привязку имени пользователя к значению ObjectDataProvider целиком. Обычно в форму не передаются параметры примитивных типов, поэтому такая хитрость не требуется. 

Например, если бы мы передавали в форму параметр созданного нами класса UserInfo со свойством UserName, то тег для ObjectDataProvider имел бы вид <ObjectDataProvider x:Key="UserInfo" ObjectType="{x:Type local:UserInfo}" />, а привязка для свойства Text имела бы вид {Binding Path=UserName, Source={StaticResource UserInfo}}

Но для этого нам потребовалось бы создать проект общей сборки, в котором потребовалось бы разместить этот тип UserInfo (кстати, он должен быть XML-сериализуемым), и ссылаться на этот проект из BlogProject.Forms и BlogProject.Workflow, что усложнило бы наш чрезвычайно простой пример. Заметьте, что в форме HelloResult, приведенной ниже, данная хитрость тоже не требуется, т.к. привязка там односторонняя.

Итак, вот полный текст первой формы:
Код
[u]
    <UserControl.Resources>
     <ObjectDataProvider x:Key="UserName" ObjectType="{x:Type sys:String}" />
    [/u]
    <Grid Width="300">
     <Label Target="{Binding ElementName=UserName}" VerticalAlignment="Top">Ваше _имя:</Label>
     <TextBox x:Name="UserName" VerticalAlignment="Top" Margin="4,32,4,0" Text="{Binding Path=ObjectInstance, BindsDirectlyToSource=True, Source={StaticResource UserName}}" />
     <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="4,60,4,0">
      <forms:FormActionButton Action="Next" Margin="4,0,0,0" Padding="12,2">_Далее</forms:FormActionButton>
      <forms:FormActionButton Action="Cancel" Margin="4,0,0,0" Padding="12,2">_Отмена</forms:FormActionButton>
     </StackPanel>
    </Grid>
</UserControl>
Файл HelloInput.xaml.cs (code behind) мы не трогаем.

Создадим теперь вторую форму, которая очень похожа на первую, и отображает введенное значение. Назовем форму HelloResult:
Код
[u]
    <UserControl.Resources>
     <ObjectDataProvider x:Key="UserName" ObjectType="{x:Type sys:String}" />
    [/u]
    <StackPanel Width="300">
     <StackPanel Orientation="Horizontal" VerticalAlignment="Top">
      <TextBlock>Добро пожаловать,</TextBlock>
      <TextBlock Margin="6,0,0,0" Text="{Binding Source={StaticResource UserName}}" />
      <TextBlock>!</TextBlock>
     </StackPanel>
     <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,4,0,0">
      <forms:FormActionButton Action="Close" Margin="4,0,0,0" Padding="12,2">_Закрыть</forms:FormActionButton>
     </StackPanel>
    </StackPanel>
</UserControl>
Создаем сценарий

Теперь создаем сценарий, который будет работать на сервере сценариев и отображать пользователю последовательно две созданные формы. Сценарии создаются в проекте BlogProject.Workflow. Для создания сценария нажмите на проекте правой кнопкой и выберите «Добавить / Последовательный рабочий процесс». Сценариям тоже нужно давать осмысленные имена, поэтому назовите сценарий HelloUser.cs

Сразу после того, как отобразится дизайнер сценариев, перейдите в свойства (открываются по кнопке F4) и задайте для свойства «Класс Base» значение C3.Workflow.Activity.FlowchartDiagram. Для свойства «Description» задайте значение «Добро пожаловать» (этот текст будет отображаться не только в дизайнере, но также в АРМ на кнопке, соответствующей запущенному сценарию). Дизайнер сценария примет вид, показанный на рисунке.



Отобразите панель элементов. Если на панели элементов нет элементов, относящихся к Капелле, создайте новую вкладку панели и добавьте на нее элементы из библиотеки C3.Workflow.Activity.dll (библиотеку возьмите, например, из CoreBinaries\bin\Debug).
Для начала перетащите на панель дизайнера активность StartActivity. Затем перетащите ShowFormActivity, после чего еще один ShowFormActivity, и, наконец, FinishActivity.

Выделите первый ShowFormActivity и перейдите в окно свойств. Задайте для активности имя showInputForm, Description = «Ввод имени пользователя», FormName = «BlogProject.Forms.HelloInput». После этого дважды щелкните на активности. На странице «Параметры» нажмите кнопку «Добавить», в появившемся окне в поле «Имя параметра» напишите UserName, в поле «Тип параметра» оставьте System.String

Отметьте флажок «Исходящий параметр», т.к. имя будет приходить из формы в сценарий (см. рис.).



Затем перейдите на вкладку «Действия» и добавьте действия, которые могут быть переданы из формы (это параметры Action всех FormActionButton, расположенных на форме). Для этой активности требуется добавить действия Cancel и Next. После выполнения всех этих действий активность в дизайнере примет вид, приведенный на рисунке.



Кроме того, после добавления параметра к активности ShowFormActivity в окне свойств появилось новое свойство с именем параметра – UserName. Выберите это свойство и нажмите в столбце значиний кнопку с многоточием – отобразится диалог редактирования привязки сценария. Т.к. у нас в сценарии еще нет хранилища для имени пользователя, в диалоге переходим на страницу «Привязка к новому члену», выбираем «Создать поле» и в поле «Имя нового члена» вводим «UserName».



Теперь заполняем параметры второй активности ShowForm, отображающей форму HelloResult. Для начала сразу дважды щелкнем на активности, добавим параметр UserName типа System.String

На этот раз флажок «Исходящий параметр» оставляем неотмеченным. На странице «Действия» добавляем в соответствии с формой одно действие – Close. Теперь переходим в свойства активности и заполняем свойства следующим образом: (Name) = showResultForm, Description = Отображение результатов, FormName = BlogProject.Forms.HelloResult

Выделяем свойство UserName, нажимаем многоточие справа и в диалоге привязки выбираем уже имеющееся поле сценария с именем UserName – так мы связываем параметры наших форм.

Теперь располагаем активности так, как показано на рисунке, и рисуем соединительные стрелки. Стрелки будут определять порядок, в котором выполняется сценарий. 



Всё, сценарий готов.

Запуск сценария

Итак, сценарий готов и его нужно запустить при запуске приложения. Сделаем это опять же пока самым простым образом – создадим вкладку приложения, содержащую наш сценарий. 

Вкладку мы пока не увидим, т.к. у нас будет только одна вкладка, а в случае наличия единственной вкладки панель вкладок не отображается. Вкладка, содержащая сценарий, инициирует запуск этого сценария со стороны клиента при запуске приложения (инициализации вкладки). Запуск сценариев может инициироваться со стороны сервера, но эту тему мы рассмотрим позже.

Чтобы создать вкладку сценария, открываем файл App.config из проекта BlogProject.Forms. Мы уже создали в нем пустой элемент <application name="BlogProject" displayName="Капелла"> </application>. На самом деле внутри элемента <application> содержится список вкладок приложения, и нашу вкладку следует добавить сюда. Делаем это:
Код
<application name="BlogProject" displayName="Капелла">
  <add name="HelloUser" type="Workflow" params="BlogProject.Workflow.HelloUser"/>
</application>
Смысл типа Workflow уже задан в том же файле чуть выше, внутри элемента <applicationtypes> – это некий класс WorkflowManager. В качестве параметра он принимает имя сценария, в нашем случае это BlogProject.Workflow.HelloUser.

Теперь наше приложение готово к запуску. После запуска нам будет отображен уже не пустой экран, а форма сценария. Не очень красивая форма (теперь можно заняться дизайном smile:)), но все же простой сценарий реализован. 

Страницы: 1  2  3  4  5  6  7  8  
Павел Ерофеев
01.06.2011 13:42:27
Конфигурация проектов
Здравствуйте, Михаил.
Спасибо за интересную статью, но Вам не кажется, что для "простого" сценария требуется слишком много конфигурации? Количество файлов конфигурации довольно велико, а информация содержащаяся в них большей частью предоставляет собой мэпинг классов на интерфейсы для IoC контейнера.
02.06.2011 15:39:05
Привет, Павел. 
Если смотреть на первый скриншот из этой статьи, то да, файлов конфигурации довольно много. Но эти файлы почти не пишутся в ручную, они поставляются вместе с ядром, мы добавляем их все в проект CoreBinaries, чтобы была возможность их исправить, когда это необходимо, и для создания нового проекта (а не сценария, т.к. при создании каждого последующего сценария в файле конфигурации уже ничего менять не нужно) действительно приходится чуть-чуть редактировать эти файлы.

Каждый файл относится к своему компоненту системы, и если разносить серверы на отдельные компьютеры, например, то у каждого сервера будет свой (один) файл конфигурации. Приложение сценариев также имеет свой файл конфигурации, также как и приложение форм. Кроме того, существуют четыре файла *Provider.config, которые относятся к поставщикам. Они нужны всегда, но в отдельные файлы они вынесены, чтобы не загромождать основной файл конфигурации.  И эти файлы в основном содержат не конфигурацию IoC-контейнера, а конфигурацию WCF.

В любом случае, количество и содержимое файлов конфигурации определяется текущей архитектурой системы. И еще раз скажу, что менять конфигурацию нужно при создании проекта, а не сценария (в статье на самом деле рассказано сначала про создание проекта (вплоть до заголовка «Создаем формы»), и лишь потом про создание сценария). Да, для проекта конфигурации много, т.к. Капелла – это довольно сложная и гибкая система. На данный момент идет разработка новой архитектуры, в которой в качестве IoC-контейнера будет использован MEF, а конфигурации, в принципе, вообще не будет (на клиенте), т.к. будет поддерживаться Silverlight-клиент.
Страницы: 1  2  3  4  5  6  7  8  

Поделитесь информацией