是否有任何方法可以使用反射访问主题/通用ResourceDictionary?
我试着在Application.Resources中挖掘,但这似乎是个错误的地方。然后我试着分析了大会的ResourceStream,但也没有成功。
那么,有人知道我如何从程序集中获取上述ResourceDictionary的实例吗?
在有人问“为什么”=>之前,因为我想搞砸它。
这是我得到的最接近的,但它会抛出错误,它的某些部分无法加载,所以我假设它是一个“副本”,而不是使用的?
System.Uri resourceLocater = new System.Uri("/ASMNAME;component/themes/generic.xaml", System.UriKind.Relative);
ResourceDictionary dictionary =(ResourceDictionary) Application.LoadComponent(resourceLocater);发布于 2021-12-06 11:49:59
@CSharpie的提供解决方案很慢,因为它使用反射来调用内部库代码。但是更重要的是,它的实现是非常不安全和非常不稳定的,因为它依赖于任何时候都可以更改的非公共库代码。在生产代码中使用这种实现是不负责任和不专业的。
在引用答案的情况下,不使用反射调用FrameworkElement.FindResource的内部,只需直接调用该方法!
更好地使用公共API:
Generic.xaml
<ResourceDictionary>
<Style TargetType="{x:Type MyCustomControl}">
...
</Style>
</ResourceDictionary>下面的代码假设Generic.xaml文件位于名为"Net.Wpf“的程序集中。您可以调用Assembly.GetManifestResourceNames来获取现有资源名称的列表。
在本例中,所需的名称是"Net.Wpf.g.resources“。
然后像这样查找资源:
// Get the assembly that contains the Themes/Generic.xaml file
Assembly themesAssembly = Assembly.GetExecutingAssembly();
await using Stream themesResourceStream = themesAssembly.GetManifestResourceStream("Net.Wpf.g.resources");
using var resourceReader = new System.Resources.ResourceReader(themesResourceStream);
await using var themesBamlStream = resourceReader
.OfType<DictionaryEntry>()
.First(entry => entry.Key.Equals("themes/generic.baml"))
.Value as Stream;
using var themesBamlReader = new System.Windows.Baml2006.Baml2006Reader(themesBamlStream);
var genericXamlResources = System.Windows.Markup.XamlReader.Load(themesBamlReader) as ResourceDictionary;
Style customControlStyle = genericXamlResources[typeof(MyCustomControl)] as Style;
// *******************************
// Same can be achieved by calling
Style customControlStyle = FindResource(typeof(ShortcutButton)) as Style;注意,XAML资源字典(将构建操作设置为"Page")通常在嵌入到程序集中之前编译为BAML (二进制格式)。因此,在访问资源之前,必须将BAML转换回XAML。
发布于 2021-12-06 10:48:55
我现在让它起作用了
Assembly asm = .....
var systemResourcesType = typeof(Application).Assembly.GetType("System.Windows.SystemResources");
var ensuremethod = systemResourcesType.GetMethod("EnsureDictionarySlot", BindingFlags.NonPublic | BindingFlags.Static);
var loadMethod = ensuremethod.ReturnType.GetMethod("LoadGenericDictionary", BindingFlags.NonPublic | BindingFlags.Instance);
var resourceDictionaries = ensuremethod.Invoke(null, new[] { asm });
var resourceDictionary = (ResourceDictionary)loadMethod.Invoke(resourceDictionaries, new object[]{false});https://stackoverflow.com/questions/70243901
复制相似问题