如果没有System.Web.dll,C#Library Code如何知道它的托管应用程序类型?

时间:2011-03-01 12:05:56

标签: c# .net iis

我们正在Windows上使用C#和.NET 4.0在Visual Studio 2010中开发多个应用程序。两个SilverLight应用程序使用来自多个WCF项目的服务。另一个是控制台应用程序。

我们希望在一个单独的库项目中放置一些“通用”功能,以便分解和重用代码。由于文件路径处理不同,该库需要知道应用程序是托管(IIS,ASP.NET ...),如WCF服务还是作为控制台应用程序运行。

谷歌搜索这个问题,人们表示使用System.Web.dll以了解代码是否托管,使用HttpContext,HostingEnvironment.IsHosted ......问题是这种方法需要包含对System的引用。 Web int the Library项目,如果此库将由具有客户端配置文件的Console项目引用,则不可接受。

这个想法是使用另一种不涉及使用System.Web程序集的技术。

6 个答案:

答案 0 :(得分:8)

如果您只需要获取包含该应用程序的文件夹中的文件的路径(如问题评论中所述),您可以使用:

Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "filename")

对于ASP.NET应用程序,这将是根文件夹(与MapPath(“〜/”+ filename)相同),对于控制台应用程序,它将是包含可执行文件的文件夹。

从评论到原始问题:

  

运行控制台应用程序时,只需使用文件名作为相对路径

我不建议使用相对路径。这将与当前工作目录相关,该目录可能与应用程序目录不同。

答案 1 :(得分:8)

有几种方法可以检查应用程序是否是ASP.NET。

检查配置文件的名称

if ("web.config".Equals(Path.GetFileName(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile), StringComparison.OrdinalIgnoreCase))
{
    // ASP.NET application
}

ASP.NET应用程序没有条目程序集

if (Assembly.GetEntryAssembly() == null)
{
    // ASP.NET application
}

ASP.NET应用程序使用所有.dll文件的卷影副本。但是,我不确定这在其他类型的应用程序中是否可行。

if (AppDomain.CurrentDomain.ShadowCopyFiles)
{
    // ASP.NET application (probably)
}

答案 2 :(得分:4)

另一个反思:使用System.Web,但通过反射:

  1. 使用AppDomain.CurrentDomain.GetAssemblies()查看是否已加载System.Web;如果没有,你就不会被托管
  2. 如果已加载,请使用反射来调用HostingEnvironment.IsHosted

  3. 事实证明,说起来容易做起来难,但这似乎可以解决问题:

    public static bool IsHosted()
    {
      try
      {
        var webAssemblies = AppDomain.CurrentDomain.GetAssemblies()
          .Where(a => a.FullName.StartsWith("System.Web"));
        foreach(var webAssembly in webAssemblies)
        {
          var hostingEnvironmentType = webAssembly.GetType("System.Web.Hosting.HostingEnvironment");
          if (hostingEnvironmentType != null)
          {
            var isHostedProperty = hostingEnvironmentType.GetProperty("IsHosted",
              BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public);
            if (isHostedProperty != null)
            {
              object result = isHostedProperty.GetValue(null, null);
              if (result is bool)
              {
                return (bool) result;
              }
            }
          }
        }
      }
      catch (Exception)
      {
        // Failed to find or execute HostingEnvironment.IsHosted; assume false
      }
      return false;
    }
    

    反射可能很昂贵,因此执行一次并缓存结果。我也不确定找到特定装配和类型的最佳方法是什么,但这种方式有效。

答案 3 :(得分:1)

您可以使用GetCallingAssembly方法通过 Reflection 执行此操作。例如

public string GetPath()
{

 if(Assembly.GetCallingAssembly().FullName == "WebProjectDLLName")
 {
   //From web project 
 }
 else
 {
   // other than web project
 }
}

虽然它不是通用解决方案,但您可以使用GetReferenceAssemblies方法(在调用程序集时)来增强它。

答案 4 :(得分:0)

由于Silverlight和控制台应用程序将了解其环境,因此您可以将相关信息放在其App.config文件中,以便公共库可以通过配置访问环境信息,而不是尝试自行处理。

答案 5 :(得分:0)

可能最简单的事情是在库中创建一个枚举库,该库将用于库的不同应用程序类型。使用枚举在库中创建变量。然后让使用该库的应用程序使用该枚举设置变量,然后库将知道正在使用它的应用程序类型。

像这样:

public static enum applicationType { hosted, console};
public static applicationType applicationConsumerType = applicationType.console;

您还可以在库方法调用中创建枚举类型applicationType的参数,从而获取应用程序类型。然后无论如何,你总是知道,因为它是必需的参数。