当您的 ResolveUri 方法收到对“公共”形式的 URI(如 -//W3C//ELEMENTS XHTML Images 1.0//EN)的请求时,您的方法是否会抛出并等待随后以 http:// 开头的类似 Web 的 URI?
我没有抛出,而是将公共 URI 解析为相应的 http:// URI(然后在我的 GetEntity 方法中,我拦截了对 http:// URI 的请求)。
因此我永远不必扔,我认为这是正确的解决方案。
这是一个聪明的方法。你的字典有多大?我向您指出的库仅处理 XHTML 1.0,并且只有一个需要映射的公共 URI 库。
我使用的是“模块化”的 XHTML 1.1,所以我必须映射大约 40 个文件。
请注意,框架的行为可能已经改变!我有一个使用 .NET Framework 2 构建的库(包括我的 XhtmlUrlResolver 类),但根据应用程序(使用该库)是为 .NET 2 还是 .NET 4 构建的,它的调用方式不同。
在 .NET 2 中,当我的 ResolveUri 方法始终只透明地委托给 XmlUrlResolver 时,它会:
- 向 DTD 的公众请求 ResolveUri。
- 尝试从磁盘获取 DTD(抛出一个 DirectoryNotFoundException)
- 尝试从 http 获取 DTD(我将从本地资源中获取)
- 尝试从 http 获取所有其他文件(我将从本地资源中获取)
在 .NET 4 中,每个资源都有一个额外的调用:
- 请求 ResolveUri 公开子资源(例如
*.mod 文件),我的实现刚刚委派给 XmlUrlResolver
- 向 GetEntity 询问子资源的“已解决”公共,这根本没有真正解决,它只是添加了一个类似 http 的前缀(抛出 WebException)
抛出所有这些 WebExceptions 会大大减慢处理速度,这就是我重新审视它以寻找修复的原因。
我从 ResolveUri 提出的您的建议解决了这个问题,对此我表示感谢;但不是抛出,而是从 ResolveUri 返回一些东西更优雅(而且更快一点:少了 40 个异常)。
这是我当前的源代码。
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.IO;
using System.Xml;
//don't obfuscate the file names of the embedded resources,
//which are contained in a "Files" subfolder of the project
[assembly: Obfuscation(Feature = "Apply to ModelText.ModelXml.Files.*: all", Exclude = true, ApplyToMembers = true)]
namespace ModelText.ModelXml
{
/// <summary>
/// This class provides local (i.e. faster) access to the XHTML DTD.
/// </summary>
/// <remarks>
/// Another way to implement this class is described in MSDN "Customizing the XmlUrlResolver Class"
/// which shows as an example a "class XmlCachingResolver"
/// and which is implemented using WebRequest and HttpRequestCachePolicy
/// </remarks>
[System.Reflection.ObfuscationAttribute(Feature = "renaming", ApplyToMembers = true)]
public class XhtmlUrlResolver : XmlResolver
{
XmlUrlResolver m_xmlUrlResolver = new XmlUrlResolver();
Assembly m_assembly = Assembly.GetExecutingAssembly();
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
string uriString = absoluteUri.ToString();
if (s_resources.uriExists(uriString))
{
//Console.WriteLine("XhtmlUrlResolver Found {0} -- {1}", uriString, DateTime.Now);
//to get the filename of the embedded resource, remove the http: directory
//this is OK because the filenames are unique and map 1-to-1 with resource names
string filename = uriString.Substring(uriString.LastIndexOf('/') + 1);
Stream stream = m_assembly.GetManifestResourceStream(typeof(XhtmlUrlResolver), "Files." + filename);
return stream;
}
//Console.WriteLine("XhtmlUrlResolver Throwing {0} -- {1}", uriString, DateTime.Now);
throw new ArgumentException();
//Console.WriteLine("XhtmlUrlResolver Getting {0} -- {1}", uriString, DateTime.Now);
//object o = m_xmlUrlResolver.GetEntity(absoluteUri, role, ofObjectToReturn);
//Console.WriteLine("XhtmlUrlResolver Got {0} -- {1}", uriString, DateTime.Now);
//return o;
}
public override Uri ResolveUri(Uri baseUri, string relativeUri)
{
string resolved = s_resources.resolve(relativeUri);
if (resolved != null)
{
//Console.WriteLine("ResolveUri resolving {0}, {1} -- {2}", baseUri, relativeUri, DateTime.Now);
return new Uri(resolved);
}
//Console.WriteLine("ResolveUri passing {0}, {1} -- {2}", baseUri, relativeUri, DateTime.Now);
return m_xmlUrlResolver.ResolveUri(baseUri, relativeUri);
}
public override System.Net.ICredentials Credentials
{
set { m_xmlUrlResolver.Credentials = value; }
}
static Resources s_resources = new Resources();
class Resources
{
Dictionary<string, string> m_publicToUri = new Dictionary<string, string>();
internal Resources()
{
for (int i = 0, n = array.GetLength(0); i < n; ++i)
{
m_publicToUri.Add(array[i, 1], array[i, 0]);
}
}
internal bool uriExists(string absoluteUri)
{
return m_publicToUri.ContainsValue(absoluteUri);
}
internal string resolve(string relativeUri)
{
string resolved;
if (m_publicToUri.TryGetValue(relativeUri, out resolved))
{
return resolved;
}
return null;
}
static string[,] array = {
{ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd", "-//W3C//DTD XHTML 1.1//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml11-model-1.mod", "-//W3C//ENTITIES XHTML 1.1 Document Model 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-attribs-1.mod", "-//W3C//ENTITIES XHTML Common Attributes 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-base-1.mod", "-//W3C//ELEMENTS XHTML Base Element 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-bdo-1.mod", "-//W3C//ELEMENTS XHTML BIDI Override Element 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-blkphras-1.mod", "-//W3C//ELEMENTS XHTML Block Phrasal 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-blkpres-1.mod", "-//W3C//ELEMENTS XHTML Block Presentation 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-blkstruct-1.mod", "-//W3C//ELEMENTS XHTML Block Structural 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-charent-1.mod", "-//W3C//ENTITIES XHTML Character Entities 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-csismap-1.mod", "-//W3C//ELEMENTS XHTML Client-side Image Maps 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-datatypes-1.mod", "-//W3C//ENTITIES XHTML Datatypes 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-edit-1.mod", "-//W3C//ELEMENTS XHTML Editing Elements 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-events-1.mod", "-//W3C//ENTITIES XHTML Intrinsic Events 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-form-1.mod", "-//W3C//ELEMENTS XHTML Forms 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-framework-1.mod", "-//W3C//ENTITIES XHTML Modular Framework 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-hypertext-1.mod", "-//W3C//ELEMENTS XHTML Hypertext 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-image-1.mod", "-//W3C//ELEMENTS XHTML Images 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-inlphras-1.mod", "-//W3C//ELEMENTS XHTML Inline Phrasal 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-inlpres-1.mod", "-//W3C//ELEMENTS XHTML Inline Presentation 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-inlstruct-1.mod", "-//W3C//ELEMENTS XHTML Inline Structural 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-inlstyle-1.mod", "-//W3C//ELEMENTS XHTML Inline Style 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-lat1.ent", "-//W3C//ENTITIES Latin 1 for XHTML//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-link-1.mod", "-//W3C//ELEMENTS XHTML Link Element 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-list-1.mod", "-//W3C//ELEMENTS XHTML Lists 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-meta-1.mod", "-//W3C//ELEMENTS XHTML Metainformation 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-object-1.mod", "-//W3C//ELEMENTS XHTML Embedded Object 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-param-1.mod", "-//W3C//ELEMENTS XHTML Param Element 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-pres-1.mod", "-//W3C//ELEMENTS XHTML Presentation 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-qname-1.mod", "-//W3C//ENTITIES XHTML Qualified Names 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-script-1.mod", "-//W3C//ELEMENTS XHTML Scripting 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-special.ent", "-//W3C//ENTITIES Special for XHTML//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-ssismap-1.mod", "-//W3C//ELEMENTS XHTML Server-side Image Maps 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-struct-1.mod", "-//W3C//ELEMENTS XHTML Document Structure 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-style-1.mod", "-//W3C//ELEMENTS XHTML Style Sheets 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-symbol.ent", "-//W3C//ENTITIES Symbols for XHTML//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-table-1.mod", "-//W3C//ELEMENTS XHTML Tables 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-target-1.mod", "-//W3C//ELEMENTS XHTML Target 1.0//EN" },
{ "http://www.w3.org/MarkUp/DTD/xhtml-text-1.mod", "-//W3C//ELEMENTS XHTML Text 1.0//EN" },
{ "http://www.w3.org/TR/ruby/xhtml-ruby-1.mod", "-//W3C//ELEMENTS XHTML Ruby 1.0//EN" }
};
}
}
}