Thursday, December 20, 2007

Model View Controller

Для более подробного описания паттерна MVC, на базе которого построен CAB крутим педали сюда:
http://rsdn.ru/article/patterns/ModelViewPresenter.xml

Wednesday, December 19, 2007

Composite UI Application Block (CAB) and Smart Client Software Factory

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


CAB - это реализация шаблонов и концепций предназначеных для создания сложных desctop приложений, словом надстройка над Win Forms.Идея CAB заключается в жесткой модульности создаваемого приложения, т.е. создаются максимально независимые друг от друга модули и реализовывается рабочий процесс внутри приложения (intra-application workflow).Жесткая модульность предназначена для повторного использования кода, что есть жЫрный +.Оболочка (UI элементы) слабо связаны с самими составными частями приложения.

Существует всего 4 слона на которых держится САВ, если говорить о САВ сервисах:
1. Загрузчик модулей и сервисы перечисления модулей
2. Сервис Event Broker
3. Сервис аутентификации
4. Сервис сохранения состояния

При создании САВ проекта сперва необходимо создать САВ-модуль, кот имеет свою точку входа.Модули находся внутри собственной DLL. Модули не требуют прямых ссылок на них из проекта оболочки в Visual Studio и непосредственной привязки к исполняемому файлу. Они загружаются в период выполнения загрузчиком модулей.

CAB-приложения базируются на шаблоне MVP/MVC (Model-View-Presenter/Model-View-Controller), который состоит из 3 элементов:
1. Presenter
2. SmartPart
3. State

Сервисы подключаются по мере необходимости в соответствии с логикой приложения. Это позволяет разработчику динамически создавать новые экземпляры объектов или возвращать объекты, уже созданные внутри контейнера. Для CAB этот контейнер является рабочим элементом и одним из первых создается разработчиком модуля. Компоненты CAB, например клиентские сервисы и рабочие пространства, можно добавлять в контейнер явно с помощью AddNew:
_rootWorkItem.WorkItems.AddNew();
То же самое можно сделать через конфигурационный файл или декларативно:

[CreateNew]
public ShipNewOrderViewPresenter Presenter{
set {
_presenter = value;
_presenter.View = this;
}
}

Внутри рабочего элемента можно переименовывать, что обеспечивает слабую связку и это позволяет добавлять любые элементы из контейнера, управляемые САВ:

[ServiceDependency]
public WorkItem WorkItem{
set {
_workItem = value;
}
}

Главное что пожалуй стоит усвоить, это то что ключевым компонентом является OBjectBuilder.С помощью Object Builder(не без помощи концепции Dependency Injection) можно создавать объекты какого-либо класса или возвращать существующие, если они подходят;сопоставлять свойства и методы с аттрибутами, которые вляют на создание и именование новго объекта; удобно удалять параметры из существующих обхектов,двигаясь обратно по цепочке операций.За включение сервисов в наш модуль отвечает Dependency Injection.

Для CAB-приложения характерен следующий порядок работы.
1. Пользователь дважды щелкает EXE-файл, отображающий оболочку.
2. Оболочка появляется на рабочем столе, загружает заданные CAB-сервисы, отображает UI-элементы и загружает все сконфигурированные модули.
3. По окончании загрузки каждый модуль добавляет по рабочему элементу в свой родительский элемент, чтобы управлять подприложением и выдавать запросы к рабочему элементу на показ его содержимого в поддерживаемом рабочем пространстве.
4. Когда пользователь выбирает какой-либо элемент меню, срабатывает соответствующая команда.
5. Обработчик команд реагирует на эту команду созданием дочернего рабочего элемента, который управляет другим подприложением и отображает его представления.6. Рабочий элемент отображает свое представление с помощью Smart Part.
7. Пользователь взаимодействует с этим интерфейсом, который в свою очередь обращается к контроллеру (или его презентатору).
8. Контроллер изменяет общие данные (состояние) и связывается с хостом, используя Event Broker.
9. Event Broker отправляет актуальную информацию (контекст) другим модулям или компонентам.

Это все что я хотел сказать вкратце о САВ, теперь перейдем к примеру, т.к. часть того что сказано выше м.б. не особо понятным до тех пор пока мы это не увидим на примере:

1. Создаем новое Windows Forms приложение.
2. Добавляем в проект следующие ссылки на сборки:

Microsoft.Practices.CompositeUI
Microsoft.Practices.CompositeUI.WinForms
Microsoft.Practices.ObjectBuilder

3. Затем создаем класс приложения, в котором определяется WorkItem
public class MyFirstCABApplication :
FormShellApplication{ }

4. Реализуем метод Main:
[STAThread]public static void Main(){
new MyFirstCABApplication.Run();
}

5. Перегрузим AfterShellCreated, и вызовем его базовую реализацию и инициализируйте интерфейса

protected override void AfterShellCreated(){
base.AfterShellCreated();
// Регистрируем узел расширения,

// в данном случае - File Menu
ToolStripMenuItem fileItem = (ToolStripMenuItem) Shell.MainMenuStrip.Items["File"]; MyWorkItem.UIExtensionSites.RegisterSite( "File", fileItem.DropDownItems);
// Создаем и добавляем элементы меню в узел File Menu
ToolStripMenuItem item = new ToolStripMenuItem("Show Customer"); MyWorkItem.UIExtensionSites["File"].Add(item);
// Добавляем обработчик события "щелчок" в элемент меню

// с именем ShowCustomer MyWorkItem.Commands["ShowCustomer"].AddInvoker(item, "Click");

}

6. Создаем Smart-Part. Вводим в проект пользовательский элемент управления и добавим ссылку на пространство имен Microsoft.Practices.CompositeUI.SmartParts.После этого, добвим в свой класс аттрибут SmartPart:
[SmartPart]public partial class CustomerSmartPart : UserControl{ ...}

7. Теперь впихнем обработчик команд и отобразим SamrtPart с помощью DeckWorkspace:
[CommandHandler("ShowCustomer")]
public void ShowCustomer(object sender, EventArgs e){
Form1 mainForm = new Form1();
CustomerSmartPart sp = MyWorkItem.Items.AddNew(); mainForm.deckWorkspace1.Show(sp);
// deckWorkspace1 — элемент управления,

// перенесенный на Form1
}

В окно инструментария (toolbox) можно добавить любое рабочее пространство CAB и перенести
его на проектируемую форму подобно обычному элементу управления.

Создание модуля и инициализатора

1. Создадим библиотеку классов или элементов управления.
2. Добавим ссылки: Microsoft.Practices.CompositeUI Microsoft.Practices.ObjectBuilder
3. Добавим в проект ModuleAttribute, чтобы другие модули могли идентифицировать этот модуль в коде.
4. Добавляем в свой файл AssemblyInfo.cs:[assembly: Microsoft.Practices.CompositeUI.Module("MyFirstModule")]
5. Создаем новый класс и наследуем его от Microsoft.Practices.CompositeUI.ModuleInit
Перегружаем AddServices, чтобы иметь возможность добавлять САВ-сервисы в период выполнения, и перегружаем Load для отображения любого UI.
6. Чтобы наш модуль мог загружаться, создадим XML файл ProfileCatalog.xml, который ссылается на наш новый DDL файл с модулем. Добавим этот XML файл в основной EXE проект.
7. Каталог профиля будет выглядеть так:


8. Добавим метод Load и реализуем его в своем новом классе ModuleInit. Создаем объект WorkItem в нашем модуле с использованием метода AddNew в контексте RootWorkItem. Затем вызываем метод Run нового объекта WorkItem. Итого, мы получаем рабочее пространство по имени и передаем это рабочее пространство методу Run. В данном примере целевым является пространство DeckWorkspace с именем deckWorkspace1:

public override void Load(){
base.Load();
MyWorkItem myWorkItem = RootWorkItem.WorkItems.AddNew();
myWorkItem.Run(parentWorkItem.Workspaces["deckWorkspace1"]);
}

9. Реализуем метод Run нашего класса MyWorkItem, чтобы запустить свой собственный код:
public void Run(IWorkspace deckWorkspace){
// Используйте любой Smart Part
IMyView view = this.Items.AddNew();
deckWorkspace.Show(view);
}


Tuesday, September 11, 2007

Marshalling details

Уф, ох уж эта х64 based ОС, многое там по другому в отличие от x86.
Вот, к примеру - маршаллинг, ошибы такие выдает https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=284215

А тут вот по этому делу полезная итнфа:
http://www.mindon.net/articles/gchandle.html

Monday, August 27, 2007

XenoCode and obfuscation | Protect your Code

http://www.ishodniki.ru/art/print.php?cat=1&id=448&show=net&pr=#t10

PS: You can't be sure on 100% that your code is secure from the others but you can try to protect.

Thursday, June 28, 2007

Delete a Service

Normally it should not be necessary to manually delete a service. Uninstalling an application should remove its associated service (if any).
However, should it be necessary to manually remove a service:
Run Regedit or regedt32.

Find the registry entry:
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services
Find the service there and delete it.You may wish to look at the keys and see what files the service was using and perhaps delete them also. Note:
You will have to reboot before the list gets updated in server manager. I have had it pointed out that some programs are cunning and prevent you from removing their service easily.
(For example the spyware\malware called ‘Command Service’ - "cmdService".) These change the permissions to make it more difficult for you to delete them. For these you will have to right click on the ‘service’ in regedit (regedt32), go to permissions and grant the administrator full control before the service can be deleted.

Friday, May 25, 2007

ORACLE. TABLESPACE restriction.

Interesting note:

If you'll try to create tablespace like this:

CREATE TABLESPACE "TSPACE" NOLOGGING
DATAFILE 'D:\TSPACE.ora' SIZE 6000M AUTOEXTEND ON NEXT 5M EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;

it would be failure operation due to it size. But 1Gb tablespace was created successful.
Does anybody know where this restriction is noted?

Wednesday, April 25, 2007

PL SQL optimization request.

Interesting to discuss the situation.
The goal is to unload data from table to simple .txt file with the help of UTC_FILE.
Whole file value is approximate 50Mb.
Execution script time is approximate 30hr.
As for it is too long. The question is - how modify this script to have less time to unloading.
The average speed is 1Kb per second. Writing operation takes many time to be executed.
May be it will be correct to write more data per time that it is now occured (to take more symbols to be written in one time).
Storage procedure in package is:

create or replace
procedure export_roads is
count_num number:=0;
BEGIN
select count(DISTINCT settle_idx) cnt into count_num from ACON_ADMIN;
log_road_writer.put_line(count_num); -- Count SYNT_ID
for i in (SELECT DISTINCT settle_idx, admin_order FROM ACON_ADMIN)
loop
log_road_writer.put_line(i.settle_idx); -- SYNT_ID
if i.admin_order=8 then -- order8_id roads count
begin
SELECT count(DISTINCT a.street_name) into count_num FROM acon_road_2 a where a.order8_id=i.settle_idx order by a.street_name;
log_road_writer.put_line(count_num);
for j in (SELECT DISTINCT a.street_name, a.street_language FROM acon_road_2 a where a.order8_id=i.settle_idx order by a.street_name)
loop
log_road_writer.put_line(j.street_name);
log_road_writer.put_line(j.street_language);
SELECT DISTINCT count(a.road_link_id) into count_num FROM acon_road_2 a where a.order8_id=i.settle_idx and a.street_name=j.street_name;
log_road_writer.put_line(count_num);
for c in (SELECT DISTINCT a.road_link_id FROM acon_road_2 a where a.order8_id=i.settle_idx and a.street_name=j.street_name)
loop
log_road_writer.put_line(c.road_link_id);
end loop;
end loop;
end;
else -- builtup_id roads count
begin
SELECT count(DISTINCT a.street_name) into count_num FROM acon_road_2 a where a.builtup_id=i.settle_idx order by a.street_name;
log_road_writer.put_line(count_num);
for j in (SELECT DISTINCT a.street_name, a.street_language FROM acon_road_2 a where a.builtup_id=i.settle_idx order by a.street_name)
loop
log_road_writer.put_line(j.street_name);
log_road_writer.put_line(j.street_language);
SELECT DISTINCT count(a.road_link_id) into count_num FROM acon_road_2 a where a.builtup_id=i.settle_idx and a.street_name=j.street_name;
log_road_writer.put_line(count_num);
for c in (SELECT DISTINCT a.road_link_id FROM acon_road_2 a where a.builtup_id=i.settle_idx and a.street_name=j.street_name)
loop
log_road_writer.put_line(c.road_link_id);
end loop;
end loop;
end;
end if;
end loop;
END;
/

Wednesday, February 21, 2007

ANSI SQL vs PL/SQL vs T-SQL

I want to discuss the question of software developers habiits.
Now I'm used to make scripts with the help of ANSI SQL, it is only a habbit.
It is easier for me to use it and this point allow to make really strong queries.
What SQL subdivision language are you using? It will be intersting to see your opinion and explanations about your choice.

IMHO it is look like C, C++, Java (C#) languages line. No doubt languages like Java and C# appeared from C++ language and many really good developers use them.
But we know that C++ lang have many advantages in front of Java and C# like memory management and others. So why developers use C# and Java instead of C++? Yep, usability, confort, lifelengths and just homage to progress.

So, I use ANSI-SQL with combination of C++ and C# languages and in this blogs I'll share my thougts and opinions regarding tasks, issues and algorithms.