[C#]Injectie van .NET klassen in COM-objecten

Pagina: 1
Acties:

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
Op dit moment is mijn project zo goed als af.
Ik wil echter de mogelijkheden voor gebruik nog vergroten door eventueel COM-interop mogelijk te maken.

Het project zit ongeveer zo in elkaar:
1) Ik maak sterk gebruik van dependency injection. Tijdens de start van het programma worden alle plugins dynamisch geladen. Al deze plugins voldoen aan vaste interfaces. Deze interfaces zitten in 1 assembly.
2) Ik heb 1 klasse (met interface) die all benodigde functionaliteit ter gebruik aanbiedt.
3) Er is een COM-object dat doorheen het programma gebruikt wordt.

een kort codevoorbeeldje:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// --------------------------------- Interfaces.dll
#using COMcomponent

interface IKlasse 1 {...}
interface IKlasse 2 {...}
interface IServices
{
   IKlasse1 EenFunctie();
   COMcomponent.comp Component { get; }
   IKlasse2 Klasse2 { get; }
}
//--------------------------------- Programma.exe
#using COMcomponent
#using interfaces

class Services : IServices
{
   Services() { /*... laad klasse1 en klasse2 dynamisch uit assemblies en laad COMcomponent*/}
   private IKlasse1 klasse1;
   private IKlasse2 klasse2;
   private COMcomponent.comp component;
   IKlasse1 EenFunctie() { return klasse1; }
   COMcomponent.comp Component { get { return component; } }
   IKlasse2 Klasse2 { get { return klasse2; } }
}

//---------------------------------- Plugin.dll
#using interfaces

class Klasse1 : IKlasse1
{
    private IServices services;
    Klasse1(IServices services) { this.services = services; }
}


nu wil ik hebben dat Klasse1 een wrapper (RCW) kan zijn voor een COM-object.
Daarom moet IServices (of ook Services??) COMVisible gemaakt worden.

De vraag is nu: als alle klassen die IServices aanbiedt een overeenkomstige interface hebben die COMVisible is, is het dan voldoende dat ik de interfaces COMVisble meegeef?
Ik weet dat COM werkt met interfaces (en interfacepointers) maar ik ben op dit project liever safe than sorry...

Ik heb bovendien al gevonden dat je voor COM altijd een default-contstructor nodig hebt, dus het doorgeven van IServices zou dan via een property moeten natuurlijk.

ASSUME makes an ASS out of U and ME


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
bumpje ?

ASSUME makes an ASS out of U and ME


  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Is het de bedoeling dat jouw .Net plugins visible zijn voor COM applicaties of wil je met jouw plugins COM functionaliteit aanspreken?

Voor versie 1:
Je kunt een COMVisibleAttribute prima op een interface toepassen.

Voor versie 2:
Je moet wel goed rekening houden met het feit dat COM unmanaged code is en dat je goed alles op moet ruimen zodra je plugin door de GC geraakt wordt, maw IDisposable implementeren.

Nu met Land Rover Series 3 en Defender 90


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
beide ineens ;)

Ik wil dynamisch een COM-object laden (RCW) dat mijn .NET-code meekrijgt (dependency injection)...

Als ik die COMVisibleAttribute toepas, moet ik die dan ook toepassen op alle implementerende klassen?

want als het niet zo is, kan ik gewoon
C#:
1
[assembly: COMVisible(true)]

schrijven in de AssemblyInfo file van mijn "interfaces.dll" en kan ik dan gewoon bij het schrijven van plugins ook RCW-objecten laden die een interface implementeren...

ASSUME makes an ASS out of U and ME


  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Nee COMVisible moet je eigenlijk op je AssemblyInfo.cs zetten voor je hele assembly, maar doe het wel zoals het zou moeten en dus de hele assembly COMVisible(false) en alleen de methoden die je dus visible wil hebben COMVisible(true)

Nu met Land Rover Series 3 en Defender 90


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
Aangezien in de assembly enkel de interfaces (en een paar klassen die ook over de grens plugin/programma of plugin/plugin kunnen gaan) zitten, is het wel degelijk de bedoeling dat de hele
assembly COMVisible is.

Je bent dus zeker dat dit geen problemen geeft met de GC of andere nare problemen?

nog even voor de zekerheid:
interface IServices is COMVisible.

De klasse Services laadt een COM-object in (via de Runtime-Callable Wrapper) en geeft
zichzelf als IServices mee aan het COM-object. Dit object is gedurende de hele loop van het programma beschikbaar, dus mijn IServices klasse wordt gedurende de hele loop gepinned?
Het geladen COM-object kan via mijn IServices-klasse andere .NET objecten, maar ook een ander type COM-objecten opvragen. Ook is het mogelijk om COM-objecten op te vragen via mijn .NET-klasse.

Bovendien heb ik reeds narigheid gehad met het opvragen van COM-objecten (die plots door de GC gecollect werden, en later stond de refcounter op ongewoon hoge waarden). Gelukkig zijn deze nu wel opgelost, maar ik zou niet graag dezelfde problemen hebben.

ASSUME makes an ASS out of U and ME


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Topicstarter
[bump]ersticker

ASSUME makes an ASS out of U and ME


  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Aangezien in de assembly enkel de interfaces (en een paar klassen die ook over de grens plugin/programma of plugin/plugin kunnen gaan) zitten, is het wel degelijk de bedoeling dat de hele
assembly COMVisible is.
Ok da's dan prima
Je bent dus zeker dat dit geen problemen geeft met de GC of andere nare problemen?
Tsja problemen ga je hier sowiezo mee krijgen omdat .Net managed is en COM niet. Je zult dus in jouw plugin object altijd rekening moeten houden met het feit dat je unmanaged resources (COM bindings etc) altijd zelf op moet ruimen. Dit kun je het beste doen door het Dispose pattern te gebruiken (IDisposable) of door finalizers te implementeren. IMHO zou ik het allebei doen omdat je dan zeker weet dat alles wordt opgeruimd maar dat moet je zelf maar bepalen.
nog even voor de zekerheid:
interface IServices is COMVisible.
Klopt ten dele, alle methods die jij door IServices in je klasse implementeerd zijn COMVisible en niet de interface IServices zelf.
De klasse Services laadt een COM-object in (via de Runtime-Callable Wrapper) en geeft
zichzelf als IServices mee aan het COM-object. Dit object is gedurende de hele loop van het programma beschikbaar, dus mijn IServices klasse wordt gedurende de hele loop gepinned?
Ja zolang er unmanaged resources claimt (wat gebeurt door COM functionaliteit te gebruiken) blijft die instantie dus pinned, wat je overigens wel handmatig kunt beeindigen met Dispose etc.

Het geladen COM-object kan via mijn IServices-klasse andere .NET objecten, maar ook een ander type COM-objecten opvragen. Ook is het mogelijk om COM-objecten op te vragen via mijn .NET-klasse.
Bovendien heb ik reeds narigheid gehad met het opvragen van COM-objecten (die plots door de GC gecollect werden, en later stond de refcounter op ongewoon hoge waarden). Gelukkig zijn deze nu wel opgelost, maar ik zou niet graag dezelfde problemen hebben.
Kwestie van netjes Dispose pattern toepassen en finalizers implementeren

HTH

Nu met Land Rover Series 3 en Defender 90

Pagina: 1