wpf - loading ResourceDictionary from baml using Baml2006Reader -
how can read through baml stream contains resourcedictionaory using baml2006reader , without acually instantiating the resourcedictionary?
i can ready through regular baml contains usercontrol fine , can examine xaml tree using baml2006reader.nodetype etc.
but once reader hits resourcedictionary, baml2006reader.member.name "deferrablecontent" , baml2006reader.value contains memorystream can not parsed instance of baml2006reader. can't event instantiate reader:
system.io.endofstreamexception occurred hresult=-2147024858
message=unable read beyond end of stream. source=mscorlib stacktrace: @ system.io.memorystream.internalreadint32() @ system.windows.baml2006.baml2006reader.process_header() @ wpfapplication10.assemblyextensions.read(stream stream, list`1 result) in d:\documents\visual studio 2012\projects\wpfapplication10\wpfapplication10\assemblyextensions.cs:line 84 innerexception:
it seems whenever baml2006reader encounters element baml2006reader.member.name "deferrablecontent" followed node bamlreader.value memorystream. seems stream contains baml fragment , not have header (that's why system.windows.baml2006.baml2006reader.process_header() fails.)
so need tell baml reader read baml fragment. can done giving reader instance of system.windows.baml2006.baml2006readersettings isbamlfragment property istrue.
unfortunately both baml2006readersettings class , appropriate constructor of baml2006reader internal. need resort reflection:
private static string presentationframeworkassemblyname = "presentationframework, version=4.0.0.0, culture=neutral, publickeytoken=31bf3856ad364e35"; private static baml2006reader createbamlfragmentreader(memorystream substream, xamlschemacontext schemacontext) { var bamlsettingstype = type.gettype( "system.windows.baml2006.baml2006readersettings, " + presentationframeworkassemblyname); var settingsctor = bamlsettingstype.getconstructor(type.emptytypes); var bamlsettings = settingsctor.invoke(null); var isbamlfragmentprop = bamlsettingstype.getproperty("isbamlfragment", bindingflags.nonpublic | bindingflags.instance); isbamlfragmentprop.setvalue(bamlsettings, true, null); var ctor = typeof (baml2006reader).getconstructor( bindingflags.instance | bindingflags.nonpublic, null, new[] { typeof (stream), type.gettype( "system.windows.baml2006.baml2006schemacontext, " + presentationframeworkassemblyname), bamlsettingstype }, null); return (baml2006reader)ctor.invoke(new[] { substream, schemacontext, bamlsettings }); } usage:
var substream = reader.value memorystream; if (substream != null) { using (var subreader = createbamlfragmentreader(substream, reader.schemacontext)) { // continue reading subreader } } i know rather fragile code , hackish, heck - works (for me, currently)!
Comments
Post a Comment