Россия, г. Москва |
Промежуточная среда COM+ и служба Enterprise Services
Ниже приведен пример двух классов COM+, которые используют созданный менеджер ресурсов. Напомним, что для регистрации в качестве COM+ компоненты классы должен иметь публичный конструктор без параметров. Атрибут TransactionAttribute управляет использованием транзакций COM+. Класс SampleCrmClient2 содержит метод ReadLine, читающий из файла строчку с использованием созданного менеджера ресурсов.
[Transaction(TransactionOption.Required)] public class SampleCrmClient2: ServicedComponent { public SampleCrmClient2() { } public string ReadLine(StreamCrm crm, string fileName) { using (StreamReader reader = new StreamReader(crm.ReadFromFile(fileName))) { return line = reader.ReadLine(); } } }
Метод SampleCrmClient.DoSomeWork демонстрирует использование CRM. Смена текущей директории вызвана тем, что по умолчанию для серверных компонент COM+ текущей является директория %systemroot%\system32.
[Transaction(TransactionOption.RequiresNew)] public class SampleCrmClient1: ServicedComponent { public SampleCrmClient1() { } public void DoSomeWork(string dir) { const string fileName1 = "sample1.txt"; const string fileName2 = "sample2.txt"; Environment.CurrentDirectory = dir; StreamCrm crm = new StreamCrm(); Clerk clerk = StreamCrm.CreateClerk();
Метод производит действия с двумя файлами. Сначала в поток, связанный с первым из двух файлов, записывается некоторая строка. Собственно запись в файл в этот момент не происходит, записанные данные запоминаются в кеше менеджера ресурсов после вызова метода StreamCrm.Flush. Этот метод возвращает запись, которая помещается в журнал секретаря и будет использована при завершении транзакции.
using (StreamWriter writer = new StreamWriter(crm.WriteToFile(fileName1))) { writer.Write(Environment.CurrentDirectory); } // добавление в журнал записи clerk.WriteLogRecord(crm.Flush(fileName1));
Затем из этого файла строка считывается другим объектом COM+ класса SampleCrmClient2. Таким образом, если объекты в пределах одной транзакции будут обращаться к файлам при помощи одного экземпляра менеджера ресурсов, то изменения, внесенные одним объектом, будут видны другим объектам транзакции, но не видны снаружи до ее завершения.
String tempString = ""; using (SampleCrmClient2 client2 = new SampleCrmClient2()) { tempString = client2.ReadLine(crm, Path.GetFullPath(fileName1)); }
Считанные объектом данные записываются во второй файл.
using (StreamWriter writer = new StreamWriter(crm.WriteToFile(fileName2))) { writer.WriteLine(String.Format("Считано из файла [{0}]:", fileName1)); writer.WriteLine(tempString); } // добавление в журнал записи clerk.WriteLogRecord(crm.Flush(fileName2)); // успешное завершение транзакциии, сохранение изменений в файлах ContextUtil.SetComplete(); } }
Класс CrmTest содержит метод Main. Вместо конструкции try .. finally … Dispose в C# следует использовать оператор using с тождественным результатом. Однако в данном примере хотелось бы показать, что при использовании объектов среды EnterpriseServices/COM+ для них следует вызывать Dispose в явном или неявном (через оператор using ) виде.
class CrmTest { public static void Main() { SampleCrmClient1 client1 = new SampleCrmClient1(); try { client1.DoSomeWork(Environment.CurrentDirectory); } finally { client1.Dispose(); } } }
Кроме работы с компенсирующим менеджером ресурсов, на данном примере хотелось бы показать, что хотя сборка мусора упрощает работу программиста, но при использовании объектов с интерфейсом IDisposable всегда следует вызывать их метод Dispose (явно или неявно) для своевременного освобождения ресурсов.