【问题标题】:Reflection to avoid System.Web reference避免 System.Web 引用的反射
【发布时间】:2011-09-22 10:27:37
【问题描述】:

我有一个在 windows 和 web 中使用的共享报告 dll。我现在正在尝试将 Windows 程序移动到 .NET 4 客户端配置文件,因此需要避免 System.Web 引用。

有些时候代码需要获取网站的目录或者dll的目录。我使用了类似这样的代码:

string path;
if (HttpContext.Current != null)
{
    path = HttpContext.Current.Server.MapPath("default.aspx");
}
else
{
    path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
}

有没有办法使用反射或类似方法来避免 System.Web 引用,以便我仍然可以获得适当的路径?如果是,我该怎么做?

还有其他选择吗?

编辑 我想这样做的原因是我使用了一个可以获取样式表文件并将其应用于报告的报告系统(我对所有报告都这样做)。作为我之前在 dll 本身 mystylesheet.repss 中的设置。因此,如果我想更改样式,我只需在 dll 中更改它并将其应用于所有报告。然后,只需将适当的 repss 文件放入 Windows 和网站的根目录中即可。并找到合适的路径。

尝试对 dll 使用相对路径会导致问题。传递报告。\mystylesheet.repss 在 Windows 中工作正常,但尝试 ~/mystylesheet.repss .\mystylesheet.repss 或我能从 web 中的 dll 中想到的任何其他内容最终会在错误的目录中查找“c:\windows\system32 \inetsrv"。

我可以将设置移出到每个不同的窗口和网络应用程序,然后将其传递给计算出的完整路径,当它实际上是 dll 的内部设置时,这样做似乎倒退了。

希望这一切都有意义。

【问题讨论】:

  • 将基本路径从客户端代码传递到库中不是更好吗?
  • 我可以这样做,但不希望这样做。我只是添加一个编辑来解释我为什么要这样做。

标签: .net reflection system.web


【解决方案1】:

为什么不使用相对于AppDomain.BaseDirectory 的路径。

这将是 ASP.NET 的 Web 应用程序的根目录,以及包含控制台或 WinForms 应用程序的可执行文件的目录。

对于其他应用程序类型,它通常是一个合理的默认位置:例如,在 VSTO 2005 应用程序中,它将是包含应用程序的 VSTO 托管程序集的目录,而不是 Excel 可执行文件的路径.

如果合适,您可以支持可选配置设置(例如 appSetting),以允许 DLL 的调用者指定备用位置,同时默认为基目录。

另一个选项是允许调用者指定样式表文件的路径,该路径可以是绝对路径或相对路径。如果是相对的,则使其相对于AppDomain.BaseDirectory

if (!Path.IsPathRooted(stylesheetPath))
{
     stylesheetPath = Path.Combine(
                          AppDomain.CurrentDomain.BaseDirectory, 
                          stylesheetPath);
}
...

请注意,如果您使用相对路径,它将是相对于当前工作目录的,在应用程序的生命周期中可能会发生变化,并且与应用程序基目录不同。

【讨论】:

  • 这已经解决了我的问题。谢谢,我认为 AppDomain 会在 IIS 中提供一些不同的东西,但它会获得指向我网站的正确路径。
【解决方案2】:

如果确定位置的机制应该依赖于上下文,那么调用者将其作为构造函数或方法参数或类似的东西传入似乎是合适的。无论是直接路径还是像 Func<string, string> 这样的“路径解析器”,都将取决于您需要做什么。

【讨论】:

  • 这一次我不得不不同意 Jon Skeet。虽然在某些情况下可能需要让调用者提供路径解析器,但似乎不希望强制他这样做,而不是提供一个合理的默认值,例如使用 AppDomain.BaseDirectory 的默认值。
  • @Joe:这取决于它的使用方式,真的。我非常热衷于明确这种依赖关系——让调用者决定做什么,并在文档中指出AppDomain.BaseDirectory可能是合适的。这有点像时区 - 我故意默认为 Noda Time 中的任何特定时区,以使调用者明确做出选择。
  • 这当然是一种权衡。但我认为,如果有合理的默认值,API 会更普遍可用。与更通用的 DateTime 和 DateTimeOffset 类型相比,Noda Time 可能正在解决更具体的用例,因此您的选择可能是正确的。但另一个类比可能是String.Format,默认为当前文化是,恕我直言,正确的选择,虽然不是每个人都会同意。在考虑“约定优于配置”设计模式时,这有点类似于权衡取舍——但任何讨论可能最好留给 Programmers Stack Exchange 站点。
  • @Joe:实际上恰恰相反——Noda Time 比 DateTime 和 DateTimeOffset 更通用。我很高兴你提出了 string.Format,因为我认为当前的文化是一个非常糟糕的选择。在解析或格式化机器可读的值时,这肯定很糟糕。不变的文化将是一个更好的默认 IMO - 或者根本没有,并迫使用户做出决定。
  • Noda Time 肯定更丰富,但我认为这会使其更难访问,因此不太常用。同样,我认为默认为当前的格式化文化使 API 更易于访问,尽管我了解您的 POV 已经看到它导致的常见问题。
猜你喜欢
  • 1970-01-01
  • 2023-01-03
  • 2019-10-29
  • 2011-08-12
  • 2015-06-15
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多