EDYCJA: Zapisałem wyniki jako wpis na blogu .
Kompilator C # traktuje typy COM nieco magicznie. Na przykład to stwierdzenie wygląda normalnie ...
Word.Application app = new Word.Application();
... dopóki nie zdasz sobie sprawy, że Application
to interfejs. Wywołanie konstruktora w interfejsie? Yoiks! To faktycznie jest tłumaczone na wywołanie do, Type.GetTypeFromCLSID()
a drugie na Activator.CreateInstance
.
Dodatkowo w C # 4 można użyć argumentów innych niż ref dla ref
parametrów, a kompilator po prostu dodaje zmienną lokalną do przekazania przez odwołanie, odrzucając wyniki:
// FileName parameter is *really* a ref parameter
app.ActiveDocument.SaveAs(FileName: "test.doc");
(Tak, brakuje wielu argumentów. Czy parametry opcjonalne nie są ładne? :)
Próbuję zbadać zachowanie kompilatora i nie udaje mi się sfałszować pierwszej części. Drugą część mogę zrobić bez problemu:
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);
}
}
Chciałbym móc napisać:
Dummy dummy = new Dummy();
chociaż. Oczywiście wybuchnie w czasie egzekucji, ale to w porządku. Po prostu eksperymentuję.
Inne atrybuty dodane przez kompilator do połączonych PIA COM ( CompilerGenerated
i TypeIdentifier
) nie wydają się działać ... co to za magiczny sos?
źródło
dynamic
... jesteśmy zbyt przyzwyczajeni do statycznego / silnego pisania, aby zobaczyć, dlaczego miałoby to znaczenie poza COM.Odpowiedzi:
W żadnym wypadku nie jestem w tym ekspertem, ale ostatnio natknąłem się na to, o czym myślę, że chcesz: na klasę atrybutów CoClass .
Zobacz moją odpowiedź na podobne pytanie dotyczące interfejsu Microsoft Speech API , w którym można „utworzyć instancję” interfejsu
SpVoice
(ale tak naprawdę jest to instancjaSPVoiceClass
).źródło
Między tobą a Michaelem prawie udało ci się poskładać wszystkie elementy. Myślę, że tak to działa. (Nie napisałem kodu, więc mogę go trochę błędnie określić, ale jestem prawie pewien, że tak to działa.)
Jeśli:
następnie kod jest generowany jako (IPIAINTERFACE) Activator.CreateInstance (Type.GetTypeFromClsid (GUID OF COCLASSTYPE))
Jeśli:
wtedy kod jest generowany tak, jakbyś powiedział „nowy COCLASSTYPE ()”.
Jon, nie krępuj się zgłaszać bezpośrednio do mnie lub Sama, jeśli masz pytania dotyczące tych rzeczy. FYI, Sam jest ekspertem w tej funkcji.
źródło
Okay, to tylko po to, aby nadać odpowiedzi Michaela trochę więcej treści (jest mile widziany, jeśli chce, jeśli chce, w takim przypadku usunę ten).
Patrząc na oryginalny PIA for Word, w aplikacji występują trzy typy (ignorując zdarzenia):
Istnieją dwa interfejsy z powodów, o których Eric Lippert mówi w innej odpowiedzi . I tam, jak powiedziałeś, jest
CoClass
- zarówno pod względem samej klasy, jak i atrybutu wApplication
interfejsie.Jeśli teraz używamy łączenia PIA w C # 4, część z tego jest osadzona w wynikowym pliku binarnym ... ale nie wszystko. Aplikacja, która właśnie tworzy instancję,
Application
kończy się następującymi typami:Nie
ApplicationClass
- prawdopodobnie dlatego, że zostanie załadowany dynamicznie z rzeczywistego typu COM w czasie wykonywania.Inną interesującą rzeczą jest różnica w kodzie między wersją połączoną a wersją niepowiązaną. Jeśli zdekompilujesz wiersz
w wersji, do której się odwołuje , kończy się jako:
podczas gdy w wersji połączonej kończy się jako
Tak to wygląda „prawdziwy” PIA potrzebuje
CoClass
atrybutu, ale wersja związana nie dlatego, że nie jestCoClass
kompilator może faktycznie odniesienia. Musi to robić dynamicznie.Mogę spróbować sfałszować interfejs COM, korzystając z tych informacji i zobaczyć, czy uda mi się zmusić kompilator do połączenia go ...
źródło
Aby dodać trochę potwierdzenia do odpowiedzi Michaela:
Następujący kod kompiluje się i uruchamia:
Aby to działało, potrzebujesz zarówno opcji, jak
ComImportAttribute
iGuidAttribute
.Zwróć także uwagę na informacje, gdy najedziesz kursorem myszy na
new IFoo()
: Intellisense prawidłowo odbiera informacje: Fajnie!źródło