가져온 멤버 변환
이 항목에서는 가져오기 프로세스에서 다음 멤버를 변환하는 방법을 설명합니다.
메서드
속성
이벤트
Tlbimp.exe는 DefaultMemberAttribute를 DispID가 0인 속성 또는 메서드에 적용합니다. C# 개발자는 이 멤버를 배열로 간주해야 합니다. 자세한 내용은 프로그래밍 언어 설명서를 참조하십시오.
메서드
COM interop에서 COM 형식을 가져오는 경우 원본 COM 메서드 시그니처에 해당하는 .NET Framework 메서드 시그니처가 만들어집니다. 다음 그림과 같이 변환 프로세스 동안 COM 매개 변수, 반환 값 및 HRESULT를 .NET Framework 메서드 시그니처의 해당 항목에 매핑합니다.
메서드 시그니처 변환
다른 .NET 클래스에서와 마찬가지로 개체 뷰어 또는 리플렉션을 사용하여 메서드 구문을 검토할 수 있습니다. 기본적으로 COM 개체가 오류 HRESULT를 반환하면 런타임은 이에 해당하는 예외를 throw합니다.
속성
COM 개발자는 인터페이스에서 속성과 메서드를 선언할 수 있습니다. 모든 속성은 속성 값을 설정하고 가져오는 데 사용할 해당 접근자 메서드를 포함합니다. 가져오기 프로세스에서 인터페이스의 형식 라이브러리 설명과 속성을 메타데이터로 변환하는 경우 속성 및 해당 속성에 대한 하나 이상의 접근자 메서드가 만들어집니다.
형식 라이브러리 변환 프로세스는 다음과 같은 방법으로 속성 접근자 메서드를 변환합니다.
[propget] 특성을 포함하는 속성은 같은 형식의 관리되는 속성이 됩니다. 이때 get_propertyname이라고 하는 해당 메서드를 가집니다.
[propput] 특성 또는 [propputref] 특성을 포함하는 속성은 같은 형식의 관리되는 속성이 됩니다. 이때 set_propertyname이라고 하는 해당 메서드를 가집니다.
[propput] 특성과 [propputref] 특성을 모두 포함하는 속성은 다음과 같이 됩니다.
[propputref] 특성과 같은 형식의 관리되는 속성이 되며 set_propertyname이라는 해당 메서드를 가집니다.
이름은 let_propertyname이고 [propput] 특성과 같은 형식의 다른 접근자 메서드가 됩니다.
다음 형식 라이브러리는 원본 속성을 보여 줍니다.
형식 라이브러리 표현
interface ISample : IDispatch {
[propget] HRESULT prop1([out, retval] short *pVal);
[propput] HRESULT prop1([in] short newVal);
[propget] HRESULT prop2([out, retval] INew **pVal);
[propputref] HRESULT prop2([in] INew *newVal);
[propget] HRESULT prop3([out, retval] INew **ppINew);
[propput] HRESULT prop3([in] BSTR text);
[propputref] HRESULT prop3([in] INew *pINew);
}
변환된 속성은 다음 Visual Basic 2005 코드 부분에 나타납니다.
Public Property
Get Prop1() As Integer … End Get
Set Prop1(val as Integer) … End Set
End Property
Public Property
Get Prop2() As INew … End Get
Set Prop2(val as INew) … End Set
End Property
Public Property
Get Prop3() As INew … End Get
Set Prop3(val as INew) … End Set
End Property
Public let_prop3(String as Text)
이벤트
COM 형식 라이브러리는 이벤트에 사용되는 인터페이스를 정의할 수 있습니다. 라이브러리 내에서 이벤트의 소스가 되는 coclass는 [source] 특성을 지정하여 이벤트 인터페이스를 식별할 수 있습니다. 이벤트 싱크는 인터페이스를 구현하고 이벤트 소스는 이를 사용합니다. 형식 라이브러리에서 기술되지 않는 COM 연결 지점 인터페이스는 이벤트 싱크를 이벤트 소스에 연결합니다.
다음 IDL 코드 예제에서 Button 클래스는 IButton 인터페이스를 구현하고 IButtonEvents 인터페이스에서 이벤트의 소스가 됩니다.
interface IButton {
HRESULT Init();
}
interface IButtonEvents {
HRESULT Click([in] int x, [in] int y);
HRESULT Resize([out, retval] int *pRetval};
}
coclass Button {
[default] interface IButton;
[default, source] interface IButtonEvents;
}
.NET 이벤트 모델은 COM 연결 지점 모델과 상당히 다릅니다. 이벤트를 싱크하는 관리되는 클래스는 COM 연결 지점을 사용하는 대신 이벤트 소스에 대리자를 전달하여 이렇게 합니다. COM interop 서비스는 이러한 두 이벤트 모델을 중개하는 역할을 합니다.
가져오는 동안 Tlbimp.exe는 관리되는 응용 프로그램이 .NET 이벤트 모델을 사용하는 관리되지 않는 클래스에 의해 발생한 이벤트를 싱크할 수 있도록 하는 여러 가지 형식을 만듭니다. 다음 단계를 통해 Tlbimp.exe는 위의 예제에서 소개한 Button 클래스의 클래스와 인터페이스를 생성합니다.
가져오기 프로세스는 이벤트 인터페이스의 각 이벤트에 대해 대리자 형식을 만듭니다. 대리자 이름은 이벤트 싱크 인터페이스, 밑줄, 이벤트 이름 및 단어 EventHandler로 구성됩니다. 예를 들면 위의 예제의 형식 라이브러리에서 Click 이벤트는 IButtonEvents_ClickEventHandler 대리자가 됩니다.
' A delegate for each event. Delegate Sub IButtonEvents_ClickEventHandler(ByVal x As Integer, _ ByVal y As Integer) Delegate Function IButtonEvents_ResizeEventHandler() As Integer
// A delegate for each event. delegate void IButtonEvents_ClickEventHandler(int x, int y); delegate int IButtonEvents_ResizeEventHandler();
대리자 서명은 관리되지 않는 메서드 시그니처에서 직접 변환되었습니다.
Tlbimp.exe는 일반적인 방법으로 기본 인터페이스를 가져옵니다. 이때 인터페이스의 이름은 동일하게 유지됩니다. 이 예제에서 인터페이스는 IButton입니다.
' Direct import of original default interface. Public Interface IButton Sub Init() End Interface
// Direct import of original default interface. public interface IButton { void Init(); }
Tlbimp.exe는 일반적인 방법으로 이벤트 인터페이스를 가져옵니다. 이때 인터페이스의 이름은 동일하게 유지됩니다. 이 예제에서 인터페이스는 IButtonEvent입니다.
' Direct import of original event interface. ' Not of interest to managed sinks. Public Interface IButtonEvents Sub Click(ByVal x As Integer, ByVal y As Integer) Function Resize() As Integer End Interface
// Direct import of original event interface. // Not of interest to managed sinks. public interface IButtonEvents { void Click(int x, int y); int Resize(); }
또한 Tlbimp.exe는 원본 인터페이스의 이름 뒤에 "_Event"를 추가하여 둘째 이벤트 인터페이스를 만듭니다. 이 둘째 이벤트 인터페이스는 멤버와 같은 Click 및 Resize 이벤트를 가집니다. 또한 이벤트 대리자에 대한 add 및 remove 메서드를 가집니다. 이 예제에서 둘째 이벤트 인터페이스는 IButtonEvents_Event입니다.
' Modified version of the event interface with events ' for managed sinks.
Public Interface IButtonEvents_Event Sub Click As IButtonEvents_Click Function Resize() As IButtonEvents_Resize Sub add_Click(ByVal Click As IButtonEvents_ClickEventHandler) Sub remove_Click(ByVal Click As _ IButtonEvents_ClickEventHandler) Sub add_Resize(ByVal Resize As _ IButtonEvents_ResizeEventHandler) Sub remove_Resize(ByVal Resize As _ IButtonEvents_ResizeEventHandler) End Interface // Modified version of the event interface with events // for managed sinks. public interface IButtonEvents_Event { IButtonEvents_Click Click; IButtonEvents_Resize Resize; void add_Click(IButtonEvents_ClickEventHandler ); void remove_Click(IButtonEvents_ClickEventHandler ); void add_Resize(IButtonEvents_ResizeEventHandler ); void remove_Resize(IButtonEvents_ResizeEventHandler ); }
참고 드문 경우지만 이벤트 인터페이스로 캐스팅해야 할 경우에는 원본 인터페이스 대신 Tlbimp.exe에서 생성한 인터페이스로 캐스팅합니다.예를 들어 IButtonEvents가 아닌 IButtonEvents_Event에 캐스팅해야 합니다.
Tlbimp.exe에서는 명시적으로 구현된 모든 인터페이스를 포함할 수 있도록 이벤트의 소스가 되는 coclass를 가져와서 원본 클래스 이름 뒤에 Class를 붙입니다. 예를 들어, Button coclass는 ButtonClass가 됩니다. 또한 Tlbimp.exe에서는 coclass와 같은 이름의 coclass 인터페이스도 생성하며, 이 인터페이스는 _Event 접미사가 있는 이벤트 인터페이스를 구현합니다.
' This is the imported coclass interface. ' Note the underscore in IButtonEvents_Event. Public Interface Button Inherits IButton Inherits IButtonEvents_Event End Interface Public Class ButtonClass Implements Button Implements IButton Implements IButtonEvents_Event Sub Init() End Sub 'Init End Class
// This is the imported coclass interface. // Note the underscore in IButtonEvents_Event. public interface Button:IButton, IButtonEvents_Event {} public class ButtonClass:Button,IButton,IButtonEvents_Event { void Init(){} }