[C#] Deserializen van een resource

Pagina: 1
Acties:
  • 215 views sinds 30-01-2008
  • Reageer

  • rollebol
  • Registratie: Mei 2000
  • Laatst online: 22-08-2025
Omdat ik een klein programmaatje wil distribueren met alléén de executable, en ik in dat kleine programma een vrij grote hash map gebruik die in principe niet verandert, heb ik deze hash map geserialized en in een file gestopt. Deze file heb ik vervolgens als resource in een .resx-bestand gestopt, en deze aan mijn project gekoppeld. Dat lijkt te werken, gezien het volgende geen exception geeft:

C#:
1
2
ResourceManager resourceManager =
     new ResourceManager ("SqGen.ICAO", GetType ().Assembly);
Maar nu. Met GetObject kan ik er bij, naar het schijnt. Maar het volgende werkt niet:


C#:
1
2
deBetreffendeHashtable = (System.Collections.Hashtable)
     resourceManager.GetObject ("airportICAO");
Als ik de boven genoemde file, die ik dus in een resource heb gestopt, wil lezen, dus wil deserializen uit die file, dan gebruik ik een BinaryFormatter, en dat werkt voor een losse file prima maar die wil een stream zien, en geen resourceManager.GetObject (). Dit werkt dus ook niet:

C#:
1
2
3
BinaryFormatter bformatter = new BinaryFormatter();
deBetreffendeHashtable = (System.Collections.Hashtable)
     bformatter.Deserialize(resourceManager.GetObject ("airportICAO"));
Concreet is dus mijn vraag: Hoe stop ik een geserialized object dat in een resource zit weer terug in het programma zodat ik hem kan gebruiken?

Dit is het eerste wat ik sinds tijden met C# doe, dus het is even wennen. In Python kan je een memory stream maken die de link zou kunnen vormen tussen GetObject en de BinaryFormatter, misschien kan dat in C# ook wel. Ik heb helaas nog niet gevonden hoe, ondanks Google en MSDN. Iemand een suggestie?

Overigens is een alternatieve aanpak ook welkom, als het maar één executable blijft en ik niet vanuit code de hash map moet gaan opvullen bij het opstarten.

  • whoami
  • Registratie: December 2000
  • Laatst online: 16:53
Waarom heb je geen resourcewriter object gebruikt om die resx file te maken?
Met een ResourceManager kan je idd je resource-file accessen, maar die resourcefile zal je dan wel mbhv een resourcewriter moeten schrijven hebben, en niet zomaar serializen naar een binair bestand.

[ Voor 60% gewijzigd door whoami op 05-06-2004 13:38 ]

https://fgheysels.github.io/


  • rollebol
  • Registratie: Mei 2000
  • Laatst online: 22-08-2025
whoami schreef op 05 juni 2004 @ 13:37:
Waarom heb je geen resourcewriter object gebruikt om die resx file te maken?
Geen idee dat dit ook bestond. Ik ga ermee aan de stoei, bedankt!

  • rollebol
  • Registratie: Mei 2000
  • Laatst online: 22-08-2025
Toch nog even op terugkomen. Ik heb hier in MSDN een voorbeeld gevonden dat hem naar een file schrijft. Hoe kan ik die file (de resources in die file dus) aan mijn executable plakken? Door hem aan het project toe te voegen?

C#:
1
2
3
IResourceWriter writer = new ResourceWriter("myResources.resources");
writer.AddResource("airportICAO", icaoAirfields);
writer.Close();

Dit maakt inderdaad het bestand myResources.resources aan, maar ik weet niet hoe hem aan de executable toe te voegen...

Ik zie ook een ResxResourceWriter...

[ Voor 26% gewijzigd door rollebol op 05-06-2004 14:00 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:53
Kan je niet zo doen:

code:
1
2
3
4
5
6
7
8
ResourceWriter writer = new ResourceWriter (" myRes.resx");

foreach( DictionaryEntry entr in myHastable )
{
    writer.AddResource (entr.Key, entr.Value);
}

writer.Close();


Dan geef je aan je ResourceManager mee naar welke file hij moet zoeken
code:
1
2
3
ResourceManager resMan = new ResourceManager ("myRes", Assembly.GetExecutingAssembly);

string s = resMan.GetString ("blaat");


Zoiets ongeveer. Ik heb het niet getest, en uit de losse hand geschreven, dus don't shoot me als het niet werkt. :P
In je constructor v/d resourcemanager moet je dus de filename (zonder extensie) van je resource-file meegeven).

https://fgheysels.github.io/


  • rollebol
  • Registratie: Mei 2000
  • Laatst online: 22-08-2025
whoami schreef op 05 juni 2004 @ 14:01:
...

In je constructor v/d resourcemanager moet je dus de filename (zonder extensie) van je resource-file meegeven).
Dit zou een oplossing kunnen zijn (moet een ResxResourceWriter zijn denk ik) inderdaad. Jammer dat ik niet de hashtable kan deserializen uit de resource. Niet dat iemand het ziet, maar het lijkt me toch 'netter'. Als daar iemand nog een oplossing ervoor weet houd ik me aanbevolen.

  • rollebol
  • Registratie: Mei 2000
  • Laatst online: 22-08-2025
Hm, er gaat nog iets mis.

Met deze code heb ik de hashmap weggeschreven:
C#:
1
2
3
4
5
ResXResourceWriter writer = new ResXResourceWriter ("airfieldsICAO.resx");
foreach( DictionaryEntry entr in icaoAirfields)
{
    writer.AddResource(entr.Key.ToString(), entr.Value.ToString());
 }

Deze heb ik vervolgens aan mijn project toegevoegd (die resx file dus).

In de class is private System.Collections.Hashtable icaoAirfields; gedeclareerd, en ik laad (voordat ik er uit ga lezen natuurlijk als volgt de resource:
C#:
1
icaoAirfieldResourceMan = new ResourceManager ("airfieldsICAO", this.GetType().Assembly);



Vervolgens geeft icaoAirfieldResourceMan.GetString (icao); een exception.

[ Voor 3% gewijzigd door rollebol op 05-06-2004 14:35 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:53
Welke exception ?

https://fgheysels.github.io/


  • rollebol
  • Registratie: Mei 2000
  • Laatst online: 22-08-2025
An unhandled exception of type 'System.Resources.MissingManifestResourceException' occurred in mscorlib.dll

Additional information: Er is geen enkele geschikte bron voor de opgegeven cultuur (of de neutrale cultuur) in de gegeven assembly gevonden. Controleer of airfieldsICAO.resources juist is ingesloten of gekoppeld in assembly SqGen.
baseName: airfieldsICAO locationInfo: <null> resource file name: airfieldsICAO.resources assembly: SqGen, Version=1.0.1619.3071, Culture=neutral, PublicKeyToken=53b888d4f88ce5c3
Als ik de resource file open dan zie ik echter wel al die keys staan, en de file heet 'airfieldsICAO.resx', dus dat lijkt me wel ongeveer juist. Ik hoef hem toch alleen maar aan de solution toe te voegen ('add existing file') toch?

Edit: Bij nader inzien. Hier wordt gevraagd om een 'airfieldsICAO.resources', niet om 'airfieldsICAO.resx'. Als ik echter zo'n resources-bestand probeer toe te voegen aan het project, dan kan ik door te dubbelklikken niet zien wat er in zit, bij de resx wel...

[ Voor 66% gewijzigd door rollebol op 07-06-2004 02:46 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:53
Doe het toch eens met een resx file, en geef eens de namespace-name waarin die resx file zich bevindt ook mee aan de constructor v/d resourcemanager:

code:
1
ResourceManager resMan = new ResourceManager ("namespacename.resourcefilenamewithoutextension", ... );

https://fgheysels.github.io/


  • rollebol
  • Registratie: Mei 2000
  • Laatst online: 22-08-2025
Forgive my ignorance, maar als ik new ResXResourceWriter ("airfieldsICAO.resx"); doe, wat is dan de namespacename? De resourcefilenamewithoutextension is airfieldsICAO vermoed ik...

Ik kan het helaas vanavond pas proberen, ik wil alvast nu even zeggen dat ik je hulp zeer waardeer. Door de ResX- en Resources-bomen het MSDN-bos niet meer.

  • whoami
  • Registratie: December 2000
  • Laatst online: 16:53
Blijkbaar zal je je resource-file (dat de fallback resource is) moeten meecompilen en embedden in je assembly.
Je kan dan voor iedere andere culture een satellite assembly maken met daarin de resources voor die culture.
Of, je zal je naam moeten aanpassen van je resource file; bv:
mystrings.nl.resources oid. Lees eens iets in de MSDN over de naming conventions van resource files etc...

Kijk ook eens naar resgen.exe

[ Voor 26% gewijzigd door whoami op 07-06-2004 09:50 ]

https://fgheysels.github.io/

Pagina: 1