WPF C# Reflection: Iterate over all resources with build action "Page"
Asked Answered
S

1

0

I have a .dll with a lot of ResourceDictionaries.

The build action of all these ResourceDictionaries is set to "Page".

Inside the Dll, I want to find all these ResourceDictionaries and iterate over them.

If I set the build action to "EmbeddedResource", I can use Reflection:

var embeddedResources = Assembly.GetExecutingAssembly().GetManifestResourceNames().ToList();

But GetManifestResourceNames() does not work for resources with build action "Page".

How do I find or iterate over all resources that have the build action "page"?

The solution doesn't have to be Reflection. Any other way is very welcome.

Thank you!

Solution:

Ladies and Gentleman! I have to announce, that the man of the week and the winner of this bounty, is Mr. Jon Wu. Jon Wu gave the right hint and through searching, I found this solution:

Enumerating .NET assembly resources at runtime

The working code, slightly changed looks like this:

public static string[] GetResourceNames()
    {
        var asm = Assembly.GetExecutingAssembly();
        string resName = asm.GetName().Name + ".g.resources";
        using (var stream = asm.GetManifestResourceStream(resName))
        using (var reader = new System.Resources.ResourceReader(stream))
        {
            return reader.Cast<DictionaryEntry>().Select(entry => (string)entry.Key).ToArray();
        }
    }

If you call this method, you get all the resource strings with a ".baml" at the end and you can iterate over them.

Thank you Jon Wu for the right hint.

Shaff answered 20/6, 2017 at 22:19 Comment(8)
Is this your answer? #3314640Mancuso
@JohnPeters: No. As I explicitly wrote in the question, GetManifestResourceNames() only works for "EmbeddedResource". It does NOT work for "Page".Shaff
All "Page" marked items will go in a <WpfApplicationName>.g.resources .NET embedded resource that contains one stream per dictionary. These dictionaries are in the BAML format (en.wikipedia.org/wiki/…) so I'm not sure if this is useful. What would you want to do once you have enumerated these BAML streams?Coulee
@SimonMourier: I load them into RAM with "obj = Application.LoadComponent(uri);". The problem is, once you compile them as EmbeddedResource, this doesn't work anymore, if the ResourceDictionaries have references to each other. With references, I mean imports with Uri-Packs. For example: You have a style RD, that imports colors from another RD with: <ResourceDictionary Source="/Styles;component/Gray/Colors.xaml"/>.Shaff
Why don't you merge them in App like this #27215655 and use App.Current.Resources.MergedDictionaries?Coulee
I added the solution to the question. Thanks to everybody who helped.Shaff
You should have told us you only needed the dictionary names. My initial comment gave the solution firstCoulee
@SimonMourier It is right, that you gave the hint before Jon Wu, but I can not mark a comment as the right answer. I can only upvote them. Of course I only needed the names. If you use "EmbeddedResources" and you call Assembly.GetExecutingAssembly().GetManifestResourceNames(), you will also only get the names of the resources. I think, I made it pretty clear, that I wanted GetManifestResourceNames(), but for "Page" resources.Shaff
Y
4

According to this answer,

Page (WPF only): Used to compile a xaml file into baml. The baml is then embedded with the same technique as Resource (i.e. available as AppName.g.resources).

So it sounds like you just need to look for resources identified with YourAppName.g.resources.

Yancy answered 24/6, 2017 at 2:1 Comment(2)
LADIES AND GENTLEMAN! I have to announce, that the men of week and the winner of this bounty, are Mr. Jon Wu and Mr.Thomas Levesque. Jon Wu gave the right hint and through searching, I found this solution: #2517907. I have added the solution to the question. Thank you, John Wu!Shaff
You get the bounty, but according to the rules, I have to wait 2 hours, before I can click on the award button.Shaff

© 2022 - 2025 — McMap. All rights reserved.