문제

편집하다: 결과를 이렇게 적어봤습니다 블로그 게시물.


C# 컴파일러는 COM 유형을 다소 마술처럼 처리합니다.예를 들어, 이 문장은 정상적으로 보입니다...

Word.Application app = new Word.Application();

...당신이 그것을 깨닫기 전까지는 Application 인터페이스입니다.인터페이스에서 생성자를 호출합니까?요익스!이것은 실제로 다음 호출로 변환됩니다. Type.GetTypeFromCLSID() 그리고 또 다른 Activator.CreateInstance.

또한 C# 4에서는 참조가 아닌 인수를 사용할 수 있습니다. ref 매개변수를 사용하면 컴파일러는 참조로 전달하기 위해 지역 변수를 추가하고 결과를 삭제합니다.

// FileName parameter is *really* a ref parameter
app.ActiveDocument.SaveAs(FileName: "test.doc");

(예, 많은 주장이 누락되었습니다.선택적 매개변수가 좋지 않나요?:)

컴파일러 동작을 조사하려고 하는데 첫 번째 부분을 위조하는 데 실패했습니다.두 번째 부분은 문제 없이 수행할 수 있습니다.

using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

[ComImport, GuidAttribute("00012345-0000-0000-0000-000000000011")]
public interface Dummy
{
    void Foo(ref int x);
}

class Test
{
    static void Main()
    {
        Dummy dummy = null;
        dummy.Foo(10);
    }
}

나는 다음과 같은 글을 쓰고 싶습니다:

Dummy dummy = new Dummy();

그렇지만.분명히 실행 시간에 쾅쾅 소리가 나겠지만 괜찮습니다.나는 단지 실험 중입니다.

연결된 COM PIA에 대해 컴파일러가 추가한 다른 속성(CompilerGenerated 그리고 TypeIdentifier) 트릭을 수행하지 않는 것 같습니다 ...마법의 소스가 뭐야?

도움이 되었습니까?

해결책

제가 이 분야의 전문가는 아니지만 최근에 귀하가 원하는 것이 무엇인지 우연히 발견했습니다.그만큼 CoClass 속성 클래스.

[System.Runtime.InteropServices.CoClass(typeof(Test))]
public interface Dummy { }

Coclass는 하나 이상의 인터페이스의 콘크리트 구현을 공급합니다.Com에서는 이러한 구체적인 구현은 COM 구성 요소 개발을 지원하는 모든 프로그래밍 언어로 작성 될 수 있습니다.Delphi, C ++, Visual Basic 등

보다 Microsoft Speech API에 대한 비슷한 질문에 대한 내 대답, 인터페이스를 "인스턴스화"할 수 있습니다. SpVoice (그러나 실제로는 인스턴스화하고 있습니다. SPVoiceClass).

[CoClass(typeof(SpVoiceClass))]
public interface SpVoice : ISpeechVoice, _ISpeechVoiceEvents_Event { }

다른 팁

당신과 Michael 사이에서 당신은 거의 모든 부분을 하나로 모았습니다.나는 이것이 작동하는 방식이라고 생각합니다.(제가 코드를 작성하지 않았기 때문에 약간 잘못 설명했을 수도 있지만 이것이 어떻게 진행되는지는 확실합니다.)

만약에:

  • 인터페이스 유형을 "새로" 만들고 있으며
  • 인터페이스 유형에 알려진 coclass가 있고
  • 이 인터페이스에 "no pia" 기능을 사용하고 있습니다.

그런 다음 코드는 (IPIAINTERFACE)Activator.CreateInstance(Type.GetTypeFromClsid(GUID OF COCLASSTYPE))로 생성됩니다.

만약에:

  • 인터페이스 유형을 "새로" 만들고 있으며
  • 인터페이스 유형에 알려진 coclass가 있고
  • 이 인터페이스에 "no pia" 기능을 사용하고 있지 않습니다.

그러면 "new COCLASSTYPE()"이라고 말한 것처럼 코드가 생성됩니다.

Jon, 이 내용에 대해 질문이 있으면 언제든지 저나 Sam에게 직접 연락해 주세요.참고로 Sam은 이 기능의 전문가입니다.

좋아, 이것은 단지 Michael의 답변에 좀 더 구체적인 내용을 추가하기 위한 것입니다. (그가 원한다면 추가해도 괜찮습니다. 이 경우 저는 이것을 제거하겠습니다.)

Word.Application에 대한 원본 PIA를 보면 세 가지 유형이 관련되어 있습니다(이벤트 무시).

[ComImport, TypeLibType(...), Guid("..."), DefaultMember("Name")]
public interface _Application
{
     ...
}

[ComImport, Guid("..."), CoClass(typeof(ApplicationClass))]
public interface Application : _Application
{
}

[ComImport, ClassInterface(...), ComSourceInterfaces("..."), Guid("..."), 
 TypeLibType((short) 2), DefaultMember("Name")]
public class ApplicationClass : _Application, Application
{
}

Eric Lippert가 다음에서 설명한 이유로 두 가지 인터페이스가 있습니다. 또 다른 답변.그리고 거기에는 당신이 말했듯이 CoClass - 클래스 자체와 클래스의 속성 측면에서 모두 Application 상호 작용.

이제 C# 4에서 PIA 연결을 사용하면 일부 이 중 결과 바이너리에 포함됩니다...하지만 전부는 아닙니다.응용 프로그램 단지 의 인스턴스를 생성합니다 Application 다음 유형으로 끝납니다.

[ComImport, TypeIdentifier, Guid("..."), CompilerGenerated]
public interface _Application

[ComImport, Guid("..."), CompilerGenerated, TypeIdentifier]
public interface Application : _Application

아니요 ApplicationClass - 아마도 이는 다음에서 동적으로 로드되기 때문일 것입니다. 진짜 실행 시 COM 유형입니다.

또 다른 흥미로운 점은 링크된 버전과 링크되지 않은 버전의 코드 차이입니다.해당 라인을 디컴파일하면

Word.Application application = new Word.Application();

에서 참조됨 버전은 다음과 같이 끝납니다.

Application application = new ApplicationClass();

반면에 연결됨 버전은 다음과 같이 끝납니다

Application application = (Application) 
    Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("...")));

따라서 "진짜" PIA에는 다음이 필요한 것 같습니다. CoClass 속성이 있지만 링크된 버전은 그렇지 않습니다. 그렇지 않다CoClass 컴파일러는 실제로 참조할 수 있습니다.동적으로 수행해야 합니다.

이 정보를 사용하여 COM 인터페이스를 위조하고 컴파일러가 이를 링크하도록 할 수 있는지 알아볼 수도 있습니다.

Michael의 답변에 약간의 확인을 추가하려면 다음을 수행하십시오.

다음 코드는 컴파일되고 실행됩니다.

public class Program
{
    public class Foo : IFoo
    {
    }

    [Guid("00000000-0000-0000-0000-000000000000")]
    [CoClass(typeof(Foo))]
    [ComImport]
    public interface IFoo
    {
    }

    static void Main(string[] args)
    {
        IFoo foo = new IFoo();
    }
}

당신은 둘 다 필요합니다 ComImportAttribute 그리고 GuidAttribute 작동하려면.

또한 마우스를 위에 올려 놓을 때 정보를 확인하십시오. new IFoo():Intellisense는 다음 정보를 적절하게 수집합니다.멋진!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top