AppDomains和configSections

时间:2009-12-03 20:16:41

标签: .net configuration appdomain

我们在.NET 3.5应用程序中使用CSLA(一个相当古老的版本),我们为一些用户使用它的NetRun应用程序加载。对于那些不熟悉NetRun的人来说,NetRun.exe基本上是安装在用户计算机上的应用程序“跑步者”(例如,安装到c:\ Program Files \ NetRun \ NetRun.exe)。用户只需启动NetRun.exe即可启动应用程序。

NetRun.exe的作用如下:

(1)创建一个新的AppDomainSetup

Dim setupDomain As New AppDomainSetup()
setupDomain.ApplicationBase = CurrentDomainPath() ' this will be C:\Program Files\NetRun\
setupDomain.ConfigurationFile = "http://www.ourdomain.com/TheApp.xml" ' The app.config file is actually named TheApp.xml on the server because it has NetRun-specific config settings that don't belong in the standard TheApp.config that is used when the app is running directly from the server.

(2)然后使用该AppDomainSetup

创建一个新的AppDomain
' create new application domain 
Dim newDomain As AppDomain = AppDomain.CreateDomain("TheApp", Nothing, setupDomain)

(3)然后通过以下方式在新的AppDomain中实例化NetRun.Launcher(一个启动助手类 - 主要用于常见的启动画面):

' create launcher object in new appdomain
Dim launcher As Launcher = CType(newDomain.CreateInstanceAndUnwrap("NetRun", "NetRun.Launcher"), Launcher)

(4)然后,luncher助手类通过

在新的AppDomain中运行应用程序
' use launcher object from the new domain to launch the remote app in that appdomain
launcher.RunApp()

(5)在所有启动画面之后,应用程序最终通过

启动
Dim ass = Assembly.LoadFrom("http://www.ourdomain.com/TheApp.exe")
ass.EntryPoint.Invoke(ass.EntryPoint, Nothing)

因此,回顾一下,实际运行的应用程序的AppDomain的ApplicationBase是C:\ Program Files \ NetRun \,而实际应用程序的EntryPoint可以在“http://www.ourdomain.com/TheApp.exe”中找到。到目前为止,非常好。

除了TheApp.exe之外,应用程序本身也是对ALibrary.dll的依赖。到目前为止,这对我们来说非常有用。即使ALibrary.dll具有被拉入TheApp.xml文件的配置条目,这些配置条目也一直被读取(并继续这样做)。

在我们即将发布的版本中,我们添加了一个新的自定义配置文件部分,该部分在ALibrary.dll中定义。我们将新部分添加到TheApp.xml和TheApp.config文件

<configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.Applicat...">
      <section name="TheApp.My.MySettings" type="System.Configuration.ClientSettingsS..."/>
      <section name="ALibrary.My.MySettings" type="System.Configuration.ClientSettingsS..."/>
    </sectionGroup>
    <!-- NEW CONFIG SECTION -->
    <section name="fixedPriceExceptionModel" type="ALibrary.Configuration.FixedPrices.FixedPriceExceptionModelSection, ALibrary"/>
</configSections>

(在这篇文章中,部分内容被用来节省空间)

但是,当我们尝试访问NetRun中的新部分时,通过“正常”方式启动TheApp.exe

CType(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None) _
                             .GetSection("fixedPriceExceptionModel"), FixedPriceExceptionModelSection)

我们得到以下例外:

  

创建时出错   配置节处理程序   fixedPriceExceptionModel:不能   加载文件或程序集'ALibrary'或   其中一个依赖项。系统   找不到指定的文件。   (http://www.ourdomain.com/TheApp.xml   第8行

做一些研究,这是因为.NET配置库的程序集解析器在所有常用位置都在寻找ALibrary.dll; ApplicationBase,特定子目录,.NET核心目录,然后是GAC。不幸的是,ALibrary.dll永远不会在任何这些地方找到。当此应用程序直接在服务器上运行而没有NetRun时,应用程序不会抛出异常并正确读取配置部分。

我尝试的一件事是以不同的方式设置AppDomainSetup,因为它的ApplicationBase将设置为http://www.ourdomain.com/,但后来调用CType(newDomain.CreateInstanceAndUnwrap(“NetRun”,“NetRun.Launcher”)) ,Launcher)炸弹,因为NetRun.exe不在服务器上。

这可能需要考虑很多,我希望我能够很好地描述它(并没有让你烦恼)。也许没有简单的解决方案,但我已经用尽了我对这个领域的有限知识,并希望其他人在SO上可能有神奇的解决方案,允许我在NetRun和本地运行应用程序时可靠地访问自定义配置部分。 / p>

3 个答案:

答案 0 :(得分:2)

据我所知,问题是,代码是在客户端机器上运行的,没有组件的真实(物理)存在,因为它们是从服务器加载的。

了解它,你有两个选择:
1.努力寻找现有代码的解决方案;) 2.不使用自定义配置节处理程序。

就个人而言,我会选择#2。

不使用ALibrary.Configuration.FixedPrices.FixedPriceExceptionModelSection作为配置节处理程序(导致异常,因为在客户端上找不到此类型),而是使用默认的System.Configuration.ClientSettingsSection,如其他部分那样 - 这是其中的一部分.NET Framework,所以在客户端没有问题。之后,为所需的配置类创建一个工厂(如果你真的需要强类型),它将逐步读取配置并创建你的FixedPriceExceptionModel对象,填充数据并可供需要它的任何东西使用。

如果我误解了这个问题,请告诉我。

答案 1 :(得分:1)

我意识到这是对已经回答的问题的回复非常晚,但我已设法使用codebase元素来解决此问题。

示例(如果需要,您也可以使用file:/// url表单):

<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
             <dependentAssembly>
               <assemblyIdentity name="AssemblyName" publicKeyToken="null" culture="neutral" />
               <codeBase version="1.0.0.0" href="http://server.address.com/AssemblyLocation/AssemblyName.dll"/>
             </dependentAssembly>
          </assemblyBinding>
    </runtime>
</configuration>

另见:

Specifying an Assembly's Location

How the Runtime Locates Assemblies

答案 2 :(得分:0)

我认为这不会像你提出的那样有用。

这行代码可以工作,因为LoadFrom是一个神奇的方法,可以查看程序集及其任何依赖项的特定位置。从这个神奇的LoadFrom上下文加载App.exe及其DLL:

Dim ass = Assembly.LoadFrom("http://www.ourdomain.com/TheApp.exe")

然而,配置部分程序集加载失败,因为加载它的.NET框架代码(可能)使用普通Assembly.Load调用,该调用与原始LoadFrom调用断开连接并且没有了解www.ourdomain.com。有多种方法可以将其他目录添加到.NET程序集搜索路径中,但这些都是相对于应用程序域基本目录的。

正如您所指出的,让Assembly.Load了解www.ourdomain.com的唯一方法是更改​​app域基目录。在这种情况下,将NetRun.exe部署到Web服务器上是否太糟糕了?