Вопрос, который у меня возник, заключался в следующем: «Если я вызываю библиотечный код N методов глубоко и хочу получить пространство имен проекта - например, приложение MVC, которое на самом деле работает - как мне это получить?»
Немного хакер, но вы можете просто взять трассировку стека и отфильтровать:
public static string GetRootNamespace()
{
StackTrace stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames();
string ns = null;
foreach(var frame in stackFrames)
{
string _ns = frame.GetMethod().DeclaringType.Namespace;
int indexPeriod = _ns.IndexOf('.');
string rootNs = _ns;
if (indexPeriod > 0)
rootNs = _ns.Substring(0, indexPeriod);
if (rootNs == "System")
break;
ns = _ns;
}
return ns;
}
Все, что это делает, - получает трассировку стека, запускает методы из самых последних вызванных в root и фильтрует систему. Как только он находит системный вызов, он знает, что он зашел слишком далеко, и возвращает вам пространство имен непосредственно над ним. Независимо от того, запускаете ли вы модульный тест, приложение MVC или службу, контейнер System будет находиться на 1 уровень глубже корневого пространства имен вашего проекта, так что вуаля.
В некоторых случаях, когда системный код является промежуточным звеном (например, System.Task) на трассе, это может дать неправильный ответ. Моя цель состояла в том, чтобы взять, например, некоторый код запуска и позволить ему легко найти класс или контроллер или что-то еще в корневом пространстве имен, даже если код, выполняющий работу, находится в библиотеке. Это решает эту задачу.
Я уверен, что это можно улучшить - я уверен, что этот хакерский способ действий можно улучшить многими способами, и улучшения приветствуются.