如何通过代码启用URI-Class的IDN / IRI支持?

时间:2012-01-12 17:29:16

标签: c# uri idn

我正在尝试为URI类启用IDN / IRI支持,因为我需要在德语umlaut-domains上使用“Uri.IsWellFormedUriString”方法(例如www.bücher.de)。

我在https://stackoverflow.com/a/6107682/413531找到了类似的问题(取自http://msdn.microsoft.com/en-us/library/system.uri.aspx的“国际资源标识支持”),但解决方案对我不起作用。我当前的app.config文件如下所示:

<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="..." type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        <!-- ... some sections in here ... -->
        </sectionGroup>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <!-- ... some sections in here ... -->
        </sectionGroup>
    </configSections>
    <userSettings>
        <!-- ... some settings in here ... -->
    </userSettings>
    <applicationSettings>
        <!-- ... some settings in here ... -->
    </applicationSettings>
</configuration>

我刚刚添加

  <uri>
  <idn enabled="All" />
  <iriParsing enabled="true" />
  </uri>

作为最后的另一个子节点,抛出异常:ConfigurationErrorsException - {“Das Konfigurationssystem konnte nicht initialisiert werden。”}

所以我在http://msdn.microsoft.com/en-us/library/system.uri.aspx进一步阅读了

  

Uri类中的IRI和IDN处理也可以使用   System.Configuration.IriParsingElement,   System.Configuration.IdnElement和System.Configuration.UriSection   配置设置类。该   System.Configuration.IriParsingElement设置启用或禁用IRI   在Uri班加工。 System.Configuration.IdnElement   设置启用或禁用Uri类中的IDN处理。该   System.Configuration.IriParsingElement设置也是间接的   控制IDN。必须启用IRI处理才能进行IDN处理   可能。如果禁用IRI处理,则将进行IDN处理   设置为.NET Framework 2.0行为的默认设置   用于兼容性和IDN名称不使用。

遗憾的是,我无法找到使用System.Configuration.IriParsingElement,System.Configuration.IdnElement和System.Configuration.UriSection的示例。我不知道这些是如何使用的......

基本上,我的问题归结为:我想在URI类中启用IDN / IRI支持,但我无法弄清楚如何执行此操作。配置解决方案不适合我,所以我想通过代码尝试它,但无法弄清楚如何。顺便说一句。我也想知道为什么配置不起作用;)

2 个答案:

答案 0 :(得分:5)

这是我的解决方案,测试工作。

基本上,您需要更改System.Uri的静态非公共字段的值:

  • s_IdnScope
  • s_IriParsing

    public static bool ToggleIDNIRISupport(bool enable)
    {
        //Important: Try IsWellFormedUriString() once to initialize static fields: s_IdnScope, s_IriParsing
        Uri.IsWellFormedUriString("http://example.com/query=ü", UriKind.Absolute);
    
        //Get the assembly that contains the class
        Assembly assembly = Assembly.GetAssembly(typeof(Uri));
        if (assembly != null)
        {
            //Use the assembly in order to get the type of the class
            Type uriType = assembly.GetType("System.Uri");
            if (uriType != null)
            {
                object idnScope = uriType.InvokeMember("s_IdnScope", BindingFlags.Static | BindingFlags.GetField | BindingFlags.NonPublic, null, null, new object[] { });
                if (idnScope != null)
                {
                    if (enable)
                    {
                        uriType.InvokeMember("s_IdnScope", BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic, null, null, new object[] { UriIdnScope.All });
                    }
                    else
                    {
                        uriType.InvokeMember("s_IdnScope", BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic, null, null, new object[] { UriIdnScope.None });
                    }
                }
    
                object iriParsing = uriType.InvokeMember("s_IriParsing", BindingFlags.Static | BindingFlags.GetField | BindingFlags.NonPublic, null, null, new object[] { });
                if (iriParsing != null)
                {
                    uriType.InvokeMember("s_IriParsing", BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic, null, null, new object[] { enable });
                }
            }
        }
    
        return true;
    }
    

答案 1 :(得分:1)

我找到了一个解决方案 - 至少对于app.config部分。根据{{​​3}},如果使用.Net版本较低的4.0,则必须在app.config中添加一行:

<configSections>
  <section name="uri" type="System.Configuration.UriSection, System,
                      Version=2.0.0.0, Culture=neutral,
                      PublicKeyToken=b77a5c561934e089" />
</configSections>

添加此行后,我还可以添加

<uri>
    <idn enabled="All" />
    <iriParsing enabled="true" />
</uri>

没有收到错误。我的完整app.config现在看起来像这样:

<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="..." type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
    <!-- ... some sections in here ... -->
        </sectionGroup>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
    <!-- ... some sections in here ... -->
        </sectionGroup>

<!-- ... insert Missing section ... -->

        <section name="uri" type="System.Configuration.UriSection, System,
                      Version=2.0.0.0, Culture=neutral,
                      PublicKeyToken=b77a5c561934e089" />

    </configSections>

<!-- ... insert URI settings ... -->

    <uri>
        <idn enabled="All" />
        <iriParsing enabled="true" />
    </uri>

    <userSettings>
    <!-- ... some settings in here ... -->
    </userSettings>
    <applicationSettings>
    <!-- ... some settings in here ... -->
    </applicationSettings>
</configuration>