似乎每当 Baml2006Reader 遇到一个元素 where Baml2006Reader.Member.Name
is"DeferrableContent"
它后面跟着另一个节点 where BamlReader.Value
is a MemoryStream
。似乎这个流只包含一个 baml 片段并且没有标头(这就是System.Windows.Baml2006.Baml2006Reader.Process_Header()
失败的原因。)
所以我们需要告诉 baml 阅读器读取一个 baml 片段。这可以通过给读者一个属性System.Windows.Baml2006.Baml2006ReaderSettings
所在的实例来完成。IsBamlFragment
true
不幸的是,Baml2006ReaderSettings
类和适当的构造函数Baml2006Reader
都是内部的。所以我们需要借助反思:
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 });
}
用法:
var substream = reader.Value as MemoryStream;
if (substream != null)
{
using (var subReader = CreateBamlFragmentReader(substream, reader.SchemaContext))
{
// continue reading with subReader
}
}
我知道这是相当脆弱的代码并且非常hackish,但到底是什么 - 它有效(目前对我来说)!