Как C # Library Code может узнать, что это тип хостинга приложения без System.Web.dll? - PullRequest
8 голосов
/ 01 марта 2011

Мы разрабатываем несколько приложений в Visual Studio 2010, используя C # и .NET 4.0 в Windows.Два приложения SilverLight, использующие сервисы из нескольких проектов WCF.Другим является консольное приложение.

Мы хотим поместить некоторые «общие» функции в отдельный проект библиотеки для того, чтобы разложить и повторно использовать код.Эта библиотека должна знать, размещено ли приложение (IIS, ASP.NET ...), например, службы WCF, или запущено как консольное приложение, из-за разной обработки пути к файлу.

Поиск ответа на этот вопрос, людиуказывает на использование System.Web.dll, чтобы узнать, размещен ли код, используя HttpContext, HostingEnvironment.IsHosted ... Проблема заключается в том, что такой подход требует включения ссылки на System.Web в проекте библиотеки, посколькудопустимо, если на эту библиотеку будет ссылаться консольный проект с профилем клиента.

Идея состоит в том, чтобы использовать другой метод, не связанный с использованием сборки System.Web.

Ответы [ 6 ]

8 голосов
/ 23 марта 2012

Есть несколько способов проверить, является ли приложение 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)
}
8 голосов
/ 01 марта 2011

Если вам нужно только получить путь к файлу в папке, содержащей приложение (как в комментарии к вопросу), вы можете использовать:

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

Для приложения ASP.NET это будет корневая папка (такая же, как MapPath ("~ /" + имя файла)), для консольного приложения это будет папка, содержащая исполняемый файл.

От комментария к оригинальному вопросу:

при запуске в качестве консольного приложения, просто используйте имя файла в качестве относительного пути

Я бы не рекомендовал использовать относительный путь. Это будет относительно текущего рабочего каталога, который может отличаться от каталога приложения.

4 голосов
/ 01 марта 2011

Другая идея отражения: используйте System.Web, но через отражение:

  1. используйте AppDomain.CurrentDomain.GetAssemblies(), чтобы увидеть, загружен ли System.Web;если нет, то вы не размещены
  2. , если он загружен, используйте отражение для вызова HostingEnvironment.IsHosted

Оказывается, это легче сказать, чем сделать, но этосделайте трюк:

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;
}

Отражение, вероятно, дорого, поэтому выполните его один раз и кешируйте результат.Я также не уверен, что лучший способ найти конкретную сборку и тип, но этот способ работает.

1 голос
/ 01 марта 2011

Вы можете сделать это через Отражение с помощью метода GetCallingAssembly .Например,

public string GetPath()
{

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

Хотя это не универсальное решение, вы можете улучшить его с помощью метода GetReferenceAssemblies (при вызове сборки).

0 голосов
/ 01 марта 2011

Вероятно, самое простое, что можно сделать, - это создать в библиотеке перечисление различных типов приложений, для которых будет использоваться библиотека. Создайте переменную в библиотеке с помощью enum. Затем попросите приложение, использующее библиотеку, установить переменную с этим перечислением, и библиотека узнает, какое приложение использует ее.

Как это:

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

Вы также можете создать параметр типа перечисления applicationType, требуемый как часть вызовов метода библиотек, и таким образом получить тип приложения. Тогда независимо от того, что вы всегда знаете, так как это обязательный параметр.

0 голосов
/ 01 марта 2011

Поскольку приложения Silverlight и консольные приложения будут знать об их среде, вы можете поместить соответствующую информацию в их файлы App.config, чтобы общая библиотека могла получить доступ к информации о среде через конфигурацию, а не пытаться сама ее обработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...