EDIT: J'ai écrit les résultats sous forme de blog .
Le compilateur C # traite les types COM de manière un peu magique. Par exemple, cette déclaration semble normale ...
Word.Application app = new Word.Application();
... jusqu'à ce que vous vous rendiez compte que Application
c'est une interface. Appel d'un constructeur sur une interface? Yoiks! Cela se traduit en fait par un appel à Type.GetTypeFromCLSID()
et un autre à Activator.CreateInstance
.
De plus, en C # 4, vous pouvez utiliser des arguments non-ref pour les ref
paramètres, et le compilateur ajoute simplement une variable locale à passer par référence, en ignorant les résultats:
// FileName parameter is *really* a ref parameter
app.ActiveDocument.SaveAs(FileName: "test.doc");
(Ouais, il manque un tas d'arguments. Les paramètres optionnels ne sont-ils pas sympas? :)
J'essaie d'enquêter sur le comportement du compilateur et je n'arrive pas à simuler la première partie. Je peux faire la deuxième partie sans problème:
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);
}
}
J'aimerais pouvoir écrire:
Dummy dummy = new Dummy();
bien que. Évidemment, ça va aller au moment de l'exécution, mais ce n'est pas grave. J'expérimente juste.
Les autres attributs ajoutés par le compilateur pour les PIA COM liés ( CompilerGenerated
et TypeIdentifier
) ne semblent pas faire l'affaire ... quelle est la sauce magique?
la source
dynamic
... nous sommes trop habitués au typage statique / fort pour voir pourquoi cela importerait en dehors de COM.Réponses:
Je ne suis en aucun cas un expert en la matière, mais je suis récemment tombé sur ce que je pense que vous voulez: la classe d'attributs CoClass .
Voir ma réponse à une question similaire sur l'API Microsoft Speech , où vous pouvez «instancier» l'interface
SpVoice
(mais en réalité, vous instanciezSPVoiceClass
).la source
Entre vous et Michael, vous avez presque assemblé les morceaux. Je pense que c'est ainsi que cela fonctionne. (Je n'ai pas écrit le code, donc je le dis peut-être légèrement, mais je suis presque sûr que c'est ainsi que ça se passe.)
Si:
puis le code est généré comme (IPIAINTERFACE) Activator.CreateInstance (Type.GetTypeFromClsid (GUID OF COCLASSTYPE))
Si:
alors le code est généré comme si vous aviez dit "new COCLASSTYPE ()".
Jon, n'hésitez pas à me déranger ou à me déranger directement si vous avez des questions à ce sujet. FYI, Sam est l'expert de cette fonctionnalité.
la source
D'accord, c'est juste pour donner un peu plus de chair à la réponse de Michael (il est invité à l'ajouter s'il le souhaite, auquel cas je supprimerai celle-ci).
En regardant le PIA d'origine pour Word.Application, il existe trois types impliqués (en ignorant les événements):
Il y a deux interfaces pour des raisons dont Eric Lippert parle dans une autre réponse . Et là, comme vous l'avez dit, se trouve le
CoClass
- à la fois en termes de classe elle-même et d'attribut sur l'Application
interface.Maintenant, si nous utilisons la liaison PIA en C # 4, une partie de cela est intégrée dans le binaire résultant ... mais pas tout. Une application qui crée simplement une instance de
Application
se termine avec ces types:Non
ApplicationClass
- probablement parce que cela sera chargé dynamiquement à partir du type COM réel au moment de l'exécution.Une autre chose intéressante est la différence de code entre la version liée et la version non liée. Si vous décompilez la ligne
dans la version référencée , il se termine par:
alors que dans la version liée , il se termine par
Il semble donc que le "vrai" PIA ait besoin de l'
CoClass
attribut, mais pas la version liée car il n'y a pas deCoClass
référence que le compilateur puisse réellement référencer. Il doit le faire de manière dynamique.Je pourrais essayer de simuler une interface COM en utilisant ces informations et voir si je peux demander au compilateur de la lier ...
la source
Juste pour ajouter un peu de confirmation à la réponse de Michael:
Le code suivant se compile et s'exécute:
Vous avez besoin à la fois du
ComImportAttribute
et duGuidAttribute
pour que cela fonctionne.Notez également les informations lorsque vous passez la souris sur le
new IFoo()
: Intellisense récupère correctement les informations: Nice!la source