So erkennen Sie dynamisch alle XAML-Dateien in allen Modulen in einer Silverlight-Prisma-App

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

Das muss auf dem Silverlight-Client geschehen: Wir könnten natürlich die Projekte auf dem Entwicklungscomputer analysieren, aber das würde die Flexibilität verringern und unbenutzte Dateien in die Suche einbeziehen.

rundsätzlich möchten wir in der Lage sein, alle XAML-Dateien in einem sehr großen Prism-Projekt (unabhängig vom Laden) zu analysieren, um alle Lokalisierungszeichenfolgen zu identifizieren. Auf diese Weise können wir eine anfängliche Lokalisierungsdatenbank aufbauen, die alle unsere ressourcenbindenden Zeichenfolgen enthält, und eine Suche nach den XAML-Dateien durchführen, in denen sie vorkommen (um den Übersetzern die Bearbeitung zu erleichtern).

Warum machen Sie das ?:Das Schlimmste für Übersetzer ist, einen String nur in einem Kontext zu ändern, um herauszufinden, dass er an anderer Stelle mit einer etwas anderen Bedeutung verwendet wurde. Wir ermöglichen die kontextbezogene Bearbeitung von Übersetzungen aus der Anwendung heraus.

Update (14. September):

Die Standardmethode zum Iterieren von Assemblys steht Silverlight aus Sicherheitsgründen nicht zur Verfügung. Dies bedeutet, dass die einzige Verbesserung der folgenden 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, stehen Punkte zur Verfügung, die Sie mit anderen teilen können!

Nachverfolgen

Das Ändern des Inhalts von XAP-Dateien in einem modulbasierten Projekt scheint aus verschiedenen Gründen sehr praktisch zu sein. Geben Sie also weitere 100 Wiederholungen ein, um eine echte Antwort zu erhalten (vorzugsweise funktionierender Beispielcode). Prost und viel Glück!

Teilweise Lösung unten (funktioniert aber nicht optimal):

Below ist der Code, den ich mir ausgedacht habe und der eine Zusammenstellung von Techniken aus @ isdieser Link zu eingebetteten Ressourcen (wie von Otaku vorgeschlagen) und meine eigene Iteration des Prism-Modulkatalogs.

Problem 1 - Alle Module sind bereits geladen, daher müssen sie alle ein zweites Mal heruntergeladen werden, da ich nicht herausfinden kann, wie alle derzeit geladenen Prism-Module durchlaufen werden. Wenn jemand das Kopfgeld für dieses Exemplar teilen möchte, können Sie trotzdem helfen, dies zu einer vollständigen Lösung zu machen!

Problem 2 - Es gibt anscheinend einen Fehler im ResourceManager, der erfordert, dass Sie den Stream einer bekannten Ressource abrufen, bevor Sie alle Ressourcenelemente iterieren können (siehe Hinweis im Code unten). Das 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 er vermieden werden kann).

private void ParseAllXamlInAllModules()
{
    IModuleCatalog mm = this.UnityContainer.Resolve<IModuleCatalog>();
    foreach (var module in mm.Modules)
    {
        string xap = module.Ref;
        WebClient wc = new WebClient();
        wc.OpenReadCompleted += (s, args) =>
        {
            if (args.Error == null)
            {
                var resourceInfo = new StreamResourceInfo(args.Result, null);
                var file = new Uri("AppManifest.xaml", UriKind.Relative);
                var stream = System.Windows.Application.GetResourceStream(resourceInfo, file);
                XmlReader reader = XmlReader.Create(stream.Stream);
                var parts = new AssemblyPartCollection();
                if (reader.Read())
                {
                    reader.ReadStartElement();
                    if (reader.ReadToNextSibling("Deployment.Parts"))
                    {
                        while (reader.ReadToFollowing("AssemblyPart"))
                        {
                            parts.Add(new AssemblyPart() { Source = reader.GetAttribute("Source") });
                        }
                    }
                }
                foreach (var part in parts)
                {
                    var info = new StreamResourceInfo(args.Result, null);
                    Assembly assy = part.Load(System.Windows.Application.GetResourceStream(info, new Uri(part.Source, UriKind.Relative)).Stream);
                    // Get embedded resource names
                    string[] resources = assy.GetManifestResourceNames();
                    foreach (var resource in resources)
                    {
                        if (!resource.Contains("DummyResource.xaml"))
                        {
                            // to get the actual values - create the table
                            var table = new Dictionary<string, Stream>();
                            // All resources have “.resources” in the name – so remove it
                            var rm = new ResourceManager(resource.Replace(".resources", String.Empty), assy);
                            // Seems like some issue here, but without getting any real stream next statement doesn't work....
                            var dummy = rm.GetStream("DummyResource.xaml");
                            var rs = rm.GetResourceSet(Thread.CurrentThread.CurrentUICulture, false, true);
                            IDictionaryEnumerator enumerator = rs.GetEnumerator();
                            while (enumerator.MoveNext())
                            {
                                if (enumerator.Key.ToString().EndsWith(".xaml"))
                                {
                                    table.Add(enumerator.Key.ToString(), enumerator.Value as Stream);
                                }
                            }
                            foreach (var xaml in table)
                            {
                                TextReader xamlreader = new StreamReader(xaml.Value);
                                string content = xamlreader.ReadToEnd();
                                {
                                    // This is where I do the actual work on the XAML content
                                }
                            }
                        }
                    }
                }
            }
        };
        // Do the actual read to trigger the above callback code
        wc.OpenReadAsync(new Uri(xap, UriKind.RelativeOrAbsolute));
    }
}

Antworten auf die Frage(4)

Ihre Antwort auf die Frage