잊지 않겠습니다.

.NET으로 COM+ 객체를 만드는 예제.

.NET으로 COM+객체를 만들때는 먼저 Project Property에 Comvisible(true)로 설정이 되어 있어야지 된다. 그리고 assembly:Guid 속성에 component guid를 등록시켜야지만 com 객체를 만드는 가장 기초적인 설정이 끝이 난다. 이와같은 설정을 하면 작성된 dll이나 exe를 com+ 객체로 등록할 수 있다.

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3308202e-a355-4c3b-805d-b527d1ef5fa3")]

그러나, dll을 등록한다고해서 library안의 class들이 모두 com객체로 사용할 수 있는 것이 아니다. dll은 여러개의 com객체를 담을 수 있는 상자이고, 그 상자안에 채워야지 될 com객체들은 각각 작성되어야지 된다. com을 이용하는 것은 com 객체 뿐 아니라, com 객체를 구성하고 있는 interface역시 사용할 수 있어야지 되기 때문에, com으로 외부에서 노출될 모든 interface와 class들은 Guid Class Property를 갖고, 각 Guid 값을 가져야지 된다.

com으로 사용되기 위해서, class와 interface가 가져야지 될 속성은 각각 다른데, interface는 ComInterfaceType Property와 Guid를 가져야지 되며, class는 Com으로 제공될 ComSourceInterfaces, ClassInterface, Transaction, Guid, Com 객체 사용에서 Pool과 CreateTimeOut을 제한하는 ObjectPooling attribute를 가져야지 된다.

com interface 구현 예제
#region Interfaces

[Description("ICSSimpleObject description")]
[Guid("2A59630E-4232-4582-AE47-706E2B648579")]
// The public interface describing the COM interface of the coclass 
public interface ICSSimpleObject
{
    #region Properties

    float FloatProperty { get; set; }

    #endregion

    #region Methods

    [Description("HelloWorld description")]
    string HelloWorld();

    void GetProcessThreadID(out uint processId, out uint threadId);

    [Description("DoTransaction description")]
    void DoTransaction();

    #endregion
}

[Guid("A06C000A-7A85-42dc-BA6D-BE736B6EB97A")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
// The public interface describing the events the coclass can sink
public interface ICSSimpleObjectEvents
{
    #region Events

    [DispId(1)]
    void FloatPropertyChanging(float NewValue, ref bool Cancel);

    #endregion
}
#endregion

com class 구현 예제
// The ObjectPooling attribute is used to configure the component's object 
// pooling. It can enable or disables object pooling and set the min. or  
// max. pool size and object creation timeout. 
[ObjectPooling(MinPoolSize=2, MaxPoolSize=10, CreationTimeout=20)]
// Creates the component with a new transaction, regardless of the state 
// of the current context.
[Transaction(TransactionOption.Required)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(ICSSimpleObjectEvents))]
[Guid("14EAD156-F55E-4d9b-A3C5-658D4BB56D30")]
public class CSSimpleObject : ServicedComponent, ICSSimpleObject
{
    #region Properties

    /// 
    /// The private members don't make it into the type-library and are 
    /// hidden from the COM clients.
    /// 
    private float fField = 0;

    /// 
    /// A public property with both get and set accessor methods.
    /// 
    public float FloatProperty
    {
        get { return this.fField; }
        set
        {
            bool cancel = false;
            // Raise the event FloatPropertyChanging
            if (null != FloatPropertyChanging)
                FloatPropertyChanging(value, ref cancel);
            if (!cancel)
                this.fField = value;
        }
    }

    #endregion

    #region Methods

    /// 
    /// A public method that returns a string "HelloWorld".
    /// 
    /// "HelloWorld"
    public string HelloWorld()
    {
        return "HelloWorld";
    }

    /// 
    /// A public method with two outputs: the current process Id and the
    /// current thread Id.
    /// 
    /// [out] The current process Id
    /// [out] The current thread Id
    public void GetProcessThreadID(out uint processId, out uint threadId)
    {
        processId = NativeMethod.GetCurrentProcessId();
        threadId = NativeMethod.GetCurrentThreadId();
    }

    public void DoTransaction()
    {
        try
        {
            // Operate on the resource managers like DBMS
            // ...
	
            ContextUtil.SetComplete();  // Commit
        }
        catch (Exception ex)
        {
            ContextUtil.SetAbort();     // Rollback
            throw ex;
        }
    }

    #endregion

    #region Events

    [ComVisible(false)]
    public delegate void FloatPropertyChangingEventHandler(float NewValue, ref bool Cancel);

    /// 
    /// A public event that is fired before new value is set to the
    /// FloatProperty property. The Cancel parameter allows the client 
    /// to cancel the change of FloatProperty.
    /// 
    public event FloatPropertyChangingEventHandler FloatPropertyChanging;

    #endregion
}
Posted by Y2K
,