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