Всем привет.
Навеяно вот этими топиками:
http://www.rsdn.ru/Forum/?mid=124975Автор: SCS
Дата: 04.11.02
http://www.rsdn.ru/forum/Message.aspx?mid=125632&only=1Автор: IT
Дата: 05.11.02
ну и еще многими другими... в общем достали.
Итак почему же столько проблем с COM+-ом если компоненты, и особенно клиента создавать средствами .NET Framework?
По большому счету по двум причинам:
1. Большинство людей пытающихся создавать COM+-компоненты на .NET не указывают (явно) гуидов для всех составляющих будущей библиотеки типв.
2. Люди забывают отключить автоматическое приращение версий сборок в проектах созданных VS.NET.
Итак для того чтобы создать полноценное COM+-приложение нужно:
1. Обявить интерфейс (который в последствии будет использоваться как главный (default) интерфейс ком-объекта) отдельно от описания класса.
2. Задать гуиды для:
* Инерфейса
* Ко-класса (т.е. для класса реализующего ком-объект)
* Сборки (он будет являться LibID)
* AppID
Ниже привдены описания самых важных атрибутов и пример COM+-приложения на Шарпе:
[assembly: Guid("49E484AE-02C4-4c77-A36E-7B4ED0BCE11F")]
Гуид библиотеки типов (LibID)
[assembly: ApplicationActivation(ActivationOption.Server)]
Говорит regsvcs что COM+-приложение нужно регистрировать как серверное, а не как библиотечное (по умолчанию).
[assembly: ApplicationID("49E484AE-02C4-4c77-FFFF-7B4ED0BCE11F")]
ApplicationID в COM+-е. Его можно использовать при отладке.
[assembly: AssemblyDescription("Test AssemblyDescription")]
Превращается в атрибут helpstring в библиотеке типов.
[assembly: ApplicationName("TestNetComPlusServer")]
Имя COM+-приложения.
[assembly: AssemblyVersion("1.1.100.200")]
Версия сборки и по совместительству библиотки типов. В качестве версии библиотеки типов используется первые две цифры. Если клиент нэйтив, используется именно [version(x.x)]. Для .NET-клиентов используется полная версия сборки (!) которая помещается в custom-атрибут с ID == 90883F05-3D28-11D2-8F17-00A0C9A6186D. Например:
[
uuid(49E484AE-02C4-4C77-A36E-7B4ED0BCE11F),
version(1.1),
helpstring("Test AssemblyDescription"),
custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, TestNetComPlusServer, Version=1.1.100.200, Culture=neutral, PublicKeyToken=59079f6e6ca5a503)
]
Это все атрибуты применяемые к сборке.
Здесь ms-help://MS.VSCC/MS.MSDNVS/cpref/html/frlrfsystementerpriseserviceshierarchy.htm (System.EnterpriseServices Hierarchy) можно посмотреть список других атрибутов.
А это пример приложения созданного на Шарепе. В нем можно увидеть применение всех атрибутов и технику описания интерфейса.
[assembly: Guid("49E484AE-02C4-4c77-A36E-7B4ED0BCE11F")]
[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: ApplicationID("49E484AE-02C4-4c77-FFFF-7B4ED0BCE11F")]
[assembly: AssemblyDescription("Test AssemblyDescription")]
[assembly: ApplicationName("TestNetComPlusServer")]
// Обратите внимание на то, что версия сборки задана явно!
// Т.е. без использования знака *. Это позволяет отучить VS
// излишне беспокоиться о "правильности" версии сборки.
// И тем самым снять проблему постоянной перерегистрации
// COM+-приложения, COM+-прокси и перекомпиляции клиента.
[assembly: AssemblyVersion("1.1.100.200")]
[assembly: AssemblyDelaySign(false)]
// Строгое имя (а именно так лучше переводить "strong name")
// нужно создать утилитой Sn.exe
[assembly: AssemblyKeyFile("..\\..\\TestNetComPlusServer.snk")]
[assembly: AssemblyKeyName("")]
using System;
using System.EnterpriseServices;
using System.Runtime.InteropServices;
namespace TestNetComPlusServer
{
[GuidAttribute("FBEAA7C9-06D2-40a3-A3B7-ABC769DDA589")]
// Ип интерфейса: Dual, IDispatch или IUnknown
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IServer
{
void Method1();
};
// Переключает галочку "Component supports e&vents and statistics",
// тем самым позволяя следить за активностью компонента в Component Services
[EventTrackingEnabledAttribute(true)]
// CLSID. Сногие думают что так задается IID дефолтного интрфейса, но это не так.
[Guid("676C8C4F-7178-4023-863F-BC13658B8688")]
[ClassInterface(ClassInterfaceType.None)]
// Тут же можно задать кучу дургих атрибутов.
//[Transaction(TransactionOption.Disabled)]
public class Server: System.EnterpriseServices.ServicedComponent, IServer
{
public Server(){}
// Лдя методов тоже можно задавать атрибуты.
//[AutoComplete]
void IServer.Method1()
{
// Метод ком объекта.
int i = 0;
i = i;
}
}
}
Ниже приведен скрипт регистрирующий приложение в GAC и COM+-е:
cd bin\Debug
gacutil /i TestNetComPlusServer.dll
regsvcs /tlb:TestNetComPlusServer.tlb TestNetComPlusServer.dll
В принципе того же эффекта можно добиться изменением опций проекта.
Вот библиотека типов (реинженирнутая с помощью OLEView) получившаяся после компиляции этого проекта:
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: TestNetComPlusServer.tlb
[
uuid(49E484AE-02C4-4C77-A36E-7B4ED0BCE11F),
version(1.1),
helpstring("Test AssemblyDescription"),
custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, TestNetComPlusServer, Version=1.1.100.200, Culture=neutral, PublicKeyToken=59079f6e6ca5a503)
]
library TestNetComPlusServer
{
// TLib : // TLib : Common Language Runtime Library : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D}
importlib("mscorlib.tlb");
// TLib : : {4FB2D46F-EFC8-4643-BCD0-6E5BFA6A174C}
importlib("System.EnterpriseServices.tlb");
// TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
importlib("stdole2.tlb");
// TLib : Common Language Runtime Execution Engine 1.0 Library : {5477469E-83B1-11D2-8B49-00A0C9B7C9C4}
importlib("mscoree.tlb");
// Forward declare all types defined in this typelib
interface IServer;
[
odl,
uuid(FBEAA7C9-06D2-40A3-A3B7-ABC769DDA589),
version(1.0),
dual,
oleautomation,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, TestNetComPlusServer.IServer)
]
interface IServer : IDispatch {
[id(0x60020000)]
HRESULT Method1();
};
[
uuid(676C8C4F-7178-4023-863F-BC13658B8688),
version(1.0),
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, TestNetComPlusServer.Server)
]
coclass Server {
interface _Object;
interface IRemoteDispatch;
interface IDisposable;
interface IManagedObject;
interface System_EnterpriseServices_IServicedComponentInfo;
[default] interface IServer;
};
};
Обратите внимание на то, что все гуиды "наши". Они не изменятся ни при перекомпиляции, ни даже при изменении имен интерфейсов.... << RSDN@Home 1.0 alpha VladD2.1.0.alpha 12.1.0.1028.36665 >>