2017-05-15 5 views
1

SupposonsAjouter quelque chose à un serveur C# COM et l'utiliser à partir de C++ sans recompiler

  • Je travaille pour la société A et je fournir une DLL C# appelé managed.dll qui est COM visible. Je fournis aussi le fichier TLB appelé managed.tlb.
  • une société B utilise mon managed.dll dans un EXE C++ appelé unmanaged.exe.
  • un client C doit obtenir le managed.dll de ma compagnie A et la unmanaged.exe de la société B. La raison est que la société B ne peut pas redistribuer le managed.dll de la société A.

maintenant supposons que j'ajoute une méthode ou une propriété à l'une de mes classes dans mon managed.dll. Ensuite, le unmanaged.exe de la société B est cassé. La société B doit le recompiler avec le nouveau fichier tlb.

Comment puis-je éviter que la société B recompile leur unmanaged.exe lorsque j'ajoute quelque chose à mon managed.dll?

La raison pour laquelle je demande est

  • Je n'ai pas de contrôle lorsque la société B est recompiler ou libérer leur unmanaged.exe. Même si je fournis mon managed.dll à la compagnie B chaque fois que j'ai ajouté quelque chose.
  • Je n'ai aucun contrôle sur les versions managed.dll et unmanaged.exe que le client C utilise.
  • société B voudrais prétendre que leur unmanaged.exe V1.0 fonctionne avec mon managed.dll V1.0 ou plus récent.

Comment pouvons-nous y parvenir?

Le code source de mon managed.dll ressemble à ça:

[Guid("852e5991-ddcc-56dd-8e13-90dcaf11ebe5")] 
[ComVisible(true)] 
public interface ITestA 
{ 
    string DummyString(); 
    int DummyInt(); 
} 

[Guid("41916928-6bea-43de-bedb-318df340e7b8")] 
[ComVisible(true)] 
[ComDefaultInterface(typeof(ITestA))] 
public class TestA : ITestA 
{ 
    public string DummyString() { return "Dummy"; } 
    public int DummyInt() { return 123; } 
} 

Le fichier TLB-est généré avec RegAsm.exe managed.dll /tlb /codebase.

Le code source du unmanaged.exe ressemble que:

#include "stdafx.h" 
#import "managed.tlb" 
using namespace std; 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    HRESULT hr = CoInitialize(NULL); // Init COM 
    IClassAPtr pClassA(__uuidof(ClassA)); 
    // and so on ... 
} 

Cordialement Wollmich

+2

La modification de la disposition binaire (signatures, méthodes d'ajout/de suppression, etc.) d'une interface IUnknown publiée est quelque peu interdite. Vous devez fournir de nouvelles interfaces (comme ITestA2, ITestA3, etc.). Ou vous pouvez proposer une interface Automation (late binding/IDispatch) au lieu de s'appuyer sur des dérivées IUnknown. Mais c'est en quelque sorte plus de travail du côté C++. –

+0

@Simon Mourier: Est-ce décrit quelque part dans MSDN? Ou avez-vous une référence qui dit que je dois fournir une nouvelle interface (ITestA2) si je veux ajouter de nouvelles méthodes? – Wollmich

+0

@Wollmich: C'est l'un de ces "Il est tellement évident que nous n'avons pas besoin de l'énoncer". Chaque interface possède un identifiant unique global (GUID). Évidemment, cela n'a de sens que si le GUID identifie quelque chose d'unique. Puisque vous définissez deux interfaces (anciennes et nouvelles), il vaut mieux avoir deux ID. – MSalters

Répondre

0

Il s'est avéré que je devais fournir de nouvelles interfaces (comme ITestA2, ITestA3, etc.) si je veux ajouter de nouvelles méthodes ou propriétés à mon managed.dll.

Ainsi, le code source du managed.dll pourrait être étendue comme ça:

[Guid("5ff6c41a-6e4c-4d96-8e5e-72a560715b56")] 
[ComVisible(true)] 
public interface ITestA2 
{ 
    string DummyString(); 
    int DummyInt(); 
    bool DummyBool(); // new method 
} 

[Guid("d5b8f4b5-d33f-4e7d-866c-ef0844216a3a")] 
[ComVisible(true)] 
[ComDefaultInterface(typeof(ITestA2))] 
public class TestA2 : TestA, ITestA2 
{ 
    public bool DummyBool() { return true; } 
} 

Remarques pour

.NET

Dans les interfaces COM peuvent hériter les uns des autres. Toutefois, l'implémentation .NET qui expose l'interface .NET à COM ne prend pas en charge l'héritage. Par conséquent, vous devez répliquer les membres de l'interface dans une interface de base à l'interface dérivée.

voir COM Interop: Base class properties not exposed to COM.

1

Il y a une raison Microsoft définie IHTMLEventObj6. C'est la 5ème mise à jour incrémentale de IHTMLEventObj. Vous devrez faire la même chose: ITestA2 devra hériter ITestA et ajouter des méthodes supplémentaires.