我们正在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程序集的技术。
答案 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,但通过反射:
AppDomain.CurrentDomain.GetAssemblies()
查看是否已加载System.Web;如果没有,你就不会被托管事实证明,说起来容易做起来难,但这似乎可以解决问题:
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的参数,从而获取应用程序类型。然后无论如何,你总是知道,因为它是必需的参数。