asp.net webforms应用程序中的第三方程序集的多个版本

时间:2014-02-11 16:13:23

标签: asp.net webforms telerik

长时间潜伏,第一次海报。

背景:我有一个asp.net webforms应用程序,它当前引用包含各种Web控件的第三方程序集。第三方控件有时直接在各种页面上使用,或者是其他地方使用的用户控件的一部分。该应用程序还使用自定义服务器控件来扩展各种第三方控件。这些自定义控件也以类似的方式使用。

参考:Related Post,还有几个讨论程序集的多个版本,但我发现程序集引用的任何内容都包含webcontrols。

问题:已发现其中一个第三方控件存在IE10问题。该问题在最新版本的第三方程序集中得到解决。但是,我无法将整个应用程序完全升级到最新版本的第三方程序集。

问题:是否可以并排运行第三方组件的两个版本?

研究:我采用了其他几篇文章中提到的关于同一装配的多个版本的装配绑定方法:

<dependentAssembly>
<assemblyIdentity name="thirdParty" publicKeyToken="XXX"/>
<codeBase version="OldVersion" href="bin"/>
<codeBase version="NewVersion" href="2013/ThirdParty.dll"/>
</dependentAssembly>
</assemblyBinding>

我还在项目文件中引用了两个程序集,并为程序集的新版本添加了别名:

<Reference Include="ThirdParty, Version=OldVersion, Culture=neutral, PublicKeyToken=XXX, processorArchitecture=MSIL">
<SpecificVersion>True</SpecificVersion>
<HintPath>..\..\Library\ThirdParty.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ThirdParty, Version=NewVersion, Culture=neutral, PublicKeyToken=XXX, processorArchitecture=MSIL">
<SpecificVersion>True</SpecificVersion>
<HintPath>2013\ThirdParty.dll</HintPath>
<Private>False</Private>
<Aliases>newVersion</Aliases>
</Reference>

在我想要使用新版本控件的目标用户控件中,我有以下标记:

<%@Assembly Name="ThirdParty,  Version=NewVersion, Culture=neutral, PublicKeyToken=XXX" %>
<%@Register tagPrefix="2013" namespace="ThirdPartyNamespace" Assembly="ThirdParty,  Version=NewVersion, Culture=neutral, PublicKeyToken=XXX"  %>

在设计器代码隐藏中我有以下内容(newVersion是分配给上面引用的别名):

extern alias newVersion;

protected newVersion::ThirdParty.ControlName cbRangeType;

所有内容都构建并运行,直到我到达asp.net编译器解析标记的部分。它因CS0433错误而失败。这几乎表明cbRangeType控件的类型存在于两个不同的地方。

\ AppData \ Local \ Temp \ Temporary ASP.NET Files \ root \ 9f04cc99 \ 85cc721e \ assembly \ dl3 \ 5dc4ef04 \ _ 77c80123_27b9ce01 \ ThirdParty.DLL

\网站已\网站\ 2013 \ ThirdParty.dll'

查看生成的代码,我看到控件类型没有使用newVersion别名,而是默认的全局别名:

Line 348:        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
Line 349:        private global::ThirdParty.ControlName @__BuildControlcbRangeType() {
Line 350:            global::ThirdParty.ControlName @__ctrl;

我是否可以覆盖在用户控制级别调用BuildControl()所产生的内容?我试图做的甚至可能吗?提前谢谢。

此致 Noobian

2 个答案:

答案 0 :(得分:1)

不,这是不可能的。如果它们只是版本不同但具有相同的标识,则它们不能并排运行。使用较新的。

答案 1 :(得分:1)

  

我甚至可以覆盖调用生成的内容   用户控制级别的BuildControl()?

它更像是替换而不是覆盖,需要为用户控件重新实现整个ASP.NET build provider。 (在v4.5中它仍然是一个不可扩展的内部密封类迷宫;你可以从Mono项目/ ASP.NET vNext开始!)

  

我试图做的甚至可能吗?

在撰写本文时(v4.5),ASP.NET构建提供程序(标记代码生成器)不会发出所需的extern alias declaration + namespace alias qualifier::)组合。因此,在ASP.NET Web表单中使用多个版本的第三方控件是可能的仅适用于服务器控件(也称为自定义,Web或复合控件; 不是用户控件 with { {1}}标记...有关区别here)的详细信息。

商业级ASP.NET控件通常作为服务器控件实现,而the standard technique for using multiple versions of the same assemblyinstantiating them programmatically时可以正常工作。但是,在ASP.NET标记中无法访问具有来自不同程序集的多个版本的对象 - 所有交互都必须在代码隐藏中。在标记中使用PlaceHolder,并在CreateChildControls中将服务器控件添加到其中。通过根据需要创建方法/属性包装来访问控件。

如果示例的第三方程序集的新版本包含服务器控件:

  1. 将.ascx.designer.cs designer 代码隐藏(.ascx和成员变量)中的手动修改移动到.ascx.cs代码隐藏,以确保它们不会被覆盖。
  2. 从目标用户控件标记中删除引用第三方程序集的extern alias@Assembly指令。
  3. 将PlaceHolder添加到您希望服务器控件显示的目标用户控件标记中: @Register
  4. 将以下内容添加到您的代码隐藏中:
    <asp:PlaceHolder id="phMarkupRangeTypePlaceHolder" runat="server" />
    protected override void CreateChildControls()
    {
    base.CreateChildControls();
    this.cbRangeType = new newVersion::ThirdParty.ControlName();
    this.phMarkupRangeTypePlaceHolder.Controls.Add(this.cbRangeType);
    }
    protected string cbRangeTypeCustomProperty //-ish
    {
    get { return this.cbRangeType.CustomProperty; }
  5. PS。使用多个版本时的程序集及其依赖项require strong names