Wie alle XAML-Dateien in allen Modulen in einer Silverlight-Prism-App dynamisch erkannt werden

8

Gibt es eine einfache Möglichkeit, dynamisch alle XAML-Dateien in allen aktuell geladenen Modulen (speziell einer Silverlight Prism-Anwendung) zu finden? Ich bin mir sicher, dass dies möglich ist, aber nicht sicher, wo ich anfangen soll .

Dies muss auf dem Silverlight-Client geschehen: Wir könnten natürlich die Projekte auf dem Dev-Rechner parsen, aber das würde die Flexibilität reduzieren und ungenutzte Dateien in die Suche einbeziehen.

Grundsätzlich wollen wir alle XAML-Dateien in einem sehr großen Prism-Projekt (unabhängig vom Laden) analysieren können, um alle Lokalisierungsstrings zu identifizieren. Dadurch können wir eine erste Lokalisierungsdatenbank erstellen, die alle unsere Ressourcen-bindenden Strings enthält, und auch eine Suche nach den XAML-Dateien erstellen, in denen sie vorkommen (um die Bearbeitung für Übersetzer zu vereinfachen).

Warum das ?: Das Schlimmste für Übersetzer ist, eine Zeichenfolge in einem Kontext zu ändern, nur um festzustellen, dass sie anderswo mit etwas anderer Bedeutung verwendet wurde. Wir ermöglichen die kontextbasierte Bearbeitung von Übersetzungen aus innerhalb der Anwendung selbst.

Update (14. September):

Die Standardmethode zum Iterieren von Assemblies steht Silverlight aufgrund von Sicherheitseinschränkungen nicht zur Verfügung. Dies bedeutet, dass die einzige Verbesserung der unten aufgeführten Lösung darin besteht, wenn möglich mit der Prism-Modulverwaltung zusammenzuarbeiten. Wenn jemand eine Codelösung für den letzten Teil dieses Problems bereitstellen möchte, gibt es Punkte, die Sie mit Ihnen teilen können!

Nachverfolgung:

Das Iterieren von Inhalten von XAP-Dateien in einem Modul-Basis-Projekt scheint aus praktischen Gründen eine sehr praktische Sache zu sein, so dass man eine weitere 100 Wiederholungen aufstellen muss, um eine echte Antwort zu bekommen (vorzugsweise funktionierenden Beispielcode). Prost und viel Glück!

Teillösung unten (funktioniert aber nicht optimal):

Unten ist der Code, den ich mir ausgedacht habe, der eine Kombination von Techniken aus diesen Link zu eingebetteten Ressourcen (wie von Otaku vorgeschlagen) und meine eigene Iteration des Prism Module Catalog.

  • Problem 1 - alle Module sind schon geladen, also das ist im Grunde Sie müssen alle eine Sekunde herunterladen Zeit, wie ich nicht herausfinden kann, wie Iteriere alle aktuell geladenen Prism-Module. Wenn jemand das Kopfgeld teilen möchte auf diesem können Sie noch helfen zu machen Dies ist eine komplette Lösung!

  • Problem 2 - Es ist offensichtlich ein Fehler im erforderlichen ResourceManager Du bekommst den Strom eines Bekannten Ressource, bevor es dich lassen wird Iterieren Sie alle Ressourcenelemente (siehe Hinweis im folgenden Code). Dies bedeutet, dass ich in jedem Modul eine Dummy-Ressourcendatei haben muss. Es wäre schön zu wissen, warum dieser erste GetStream-Aufruf erforderlich ist (oder wie man ihn vermeidet).

    %Vor%
Gone Coding 09.09.2010, 14:26
quelle

2 Antworten

5

Verwenden Sie GetManifestResourceNames Reflektion und parse von dort, um nur diejenigen zu erhalten, die mit .xaml enden. Hier ein Beispiel für die Verwendung von GetManifestResourceNames : Auflisten eingebetteter Ressourcen . Obwohl das Beispiel zeigt, wie man das mit einer separaten .xap macht, können Sie dies mit dem geladenen tun.

    
Todd Main 12.09.2010, 18:04
quelle
2

Ich habe Leute gesehen, die sich über einige ziemlich große Fehler in Prism beschweren

Ihre Probleme besprechen:

Problem 1 : Ich bin mit Prism nicht vertraut, aber aus einer objektorientierten Perspektive sollte Ihre Module Manager-Klasse verfolgen, ob ein Modul geladen wurde, und falls nicht bereits geladen, können Sie es rekursiv laden Andere Module verwenden eine Kartenfunktion für den Typ List<Module> oder einen beliebigen Typ, mit dem Prism Baugruppen abstrakt darstellt. Kurz gesagt, lassen Sie Ihren Modul-Manager einen versteckten Zustand implementieren, der die Liste der geladenen Module darstellt. Ihre Map -Funktion sollte dann die Liste der bereits geladenen Module übernehmen Startwert, und geben Sie die Liste der Module zurück, die nicht geladen wurden. Sie können dann entweder die Logik für eine öffentliche LoadAllModules-Methode internalisieren oder zulassen, dass jemand eine öffentliche List<UnloadedModule> where UnloadedModule : Module iteriert und sie auswählen lässt, was geladen werden soll. Ich würde nicht empfehlen, beide Methoden gleichzeitig offenzulegen, da der Zugriff auf den Modul-Manager über mehrere Threads gleichzeitig erfolgt.

Problem 2 : Der erste Aufruf von GetStream ist erforderlich, da ResourceManager die Ressourcen langsam auswertet. Intuitiv ist meine Vermutung der Grund dafür, dass Satellitenassemblies mehrere länderspezifische Module enthalten können, und wenn alle diese Module sofort in den Speicher geladen würden, könnte dies den Heap erschöpfen und die Tatsache, dass es sich um nicht verwaltete Ressourcen handelt. Sie können den Code mit RedGate .NET Reflector betrachten, um die Details zu bestimmen. Es könnte eine billigere Methode geben, die Sie als GetStream aufrufen können. Sie können es auch auslösen, um die Assembly zu laden, indem Sie es tricksen, indem Sie eine Ressource laden, die sich in jeder Silverlight-Assembly befindet. Versuchen Sie ResourceManager.GetObject ("TOOLBAR_ICON") oder vielleicht ResourceManager.GetStream ("TOOLBAR_ICON") - Beachten Sie, dass ich dies nicht versucht habe und diesen Vorschlag eintippe, während ich für den Tag gehe. Mein Grund dafür ist, dass es immer schneller ist als Ihr SomeDummy.Xaml  Ansatz ist, dass ich glaube, TOOLBAR_ICON ist fest verdrahtet, die nullte Ressource in jeder Versammlung zu sein. So wird es sehr früh im Stream gelesen. Faaaaaast. Es ist also nicht nur notwendig, SomeDummy.Xaml in jeder Versammlung Ihres Projekts zu vermeiden, die ich vorschlage. Ich empfehle auch Mikrooptimierungen.

Wenn diese Tricks funktionieren, sollten Sie die Leistung erheblich verbessern können.

Zusätzliche Gedanken:

Ich denke, Sie können Ihren Code weiter aufräumen.

%Vor%

könnte umgestaltet werden, um den Verweis auf UnityContainer zu entfernen. Außerdem würde IModuleCatalog über einen Wrapper um das List<Module> , das ich in meiner Antwort auf Problem 1 erwähnt habe, instanziiert werden. Mit anderen Worten, IModuleCatalog wäre eine dynamische Ansicht aller geladenen Module. Ich gehe davon aus, dass es noch mehr Leistung gibt, die man aus diesem Design herausholen kann, aber zumindest sind Sie nicht mehr von Unity abhängig. Das wird dir helfen, deinen Code später besser zu refaktorieren, um mehr Leistung zu erzielen.

    
user429921 14.09.2010 00:27
quelle

Tags und Links