Sellec
@Sellec
Кодер

Как получить список типов в открытой ClassLibrary в DesignTime в VisualStudio?

Возможно, вопрос сформулирован несколько сумбурно.
Использую немного расширенный custom MvcWebPageRazorHost, встал вопрос в том, чтобы сделать автоматический импорт пространств имен (NamespacesImport) в WebPageRazorHost (дабы не прописывать довольно-таки большой список в web.config, ну и еще по ряду причин). Это должно срабатывать в runtime и designtime.

Структура примерно следующая: есть проект Core (назовем его так).
Внутри два класса:
namespace Core
{
    public class CustomWebRazorHostFactory : MvcWebRazorHostFactory
    {
        public override WebPageRazorHost CreateHost(string virtualPath, string physicalPath)
        {
            return CustomWebPageRazorHost.CreateFromAnother(base.CreateHost(virtualPath, physicalPath));
        }
    }

    class CustomWebPageRazorHost : MvcWebPageRazorHost
    {
        public static CustomWebPageRazorHost CreateFromAnother(WebPageRazorHost host)
        {
            var newHost = new CustomWebPageRazorHost(host.VirtualPath, host.PhysicalPath);

            newHost.DefaultBaseClass = typeof(CustomWebViewPage<>).FullName.Replace("`1", "");
            newHost.DefaultClassName = host.DefaultClassName;
            newHost.DefaultDebugCompilation = host.DefaultDebugCompilation;
            newHost.DefaultPageBaseClass = typeof(CustomWebViewPage<>).FullName.Replace("`1", "");
            newHost.DesignTimeMode = host.DesignTimeMode;
            newHost.EnableInstrumentation = host.EnableInstrumentation;
            newHost.GeneratedClassContext = host.GeneratedClassContext;
            newHost.InstrumentedSourceFilePath = host.InstrumentedSourceFilePath;
            newHost.IsIndentingWithTabs = host.IsIndentingWithTabs;
            newHost.TabSize = host.TabSize;

            foreach (string current in host.NamespaceImports) newHost.NamespaceImports.Add(current);

            return newHost;
        }

        protected CustomWebPageRazorHost(string s1, string s2) : base(s1, s2)
        {
            try
            {
                this.NamespaceImports.Add("System.Web.Helpers");
                this.NamespaceImports.Add("System.Web.Mvc");
                this.NamespaceImports.Add("System.Web.Mvc.Html");
                this.NamespaceImports.Add("System.Web.Routing");
                this.NamespaceImports.Add("System.Collections");

                var namespaces = Utils.ReflectionHelper.GetEngineNamespaces();
                foreach (var _namespace in namespaces)
                {
                    this.NamespaceImports.Add(_namespace);
                }

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }
    }
}


Есть проект Web (назовем его так), который подключает Core и в web.config регистрирует "host factoryType" следующим образом:
<host factoryType="Core.CustomWebRazorHostFactory, Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=..." />


Внутри GetEngineNamespaces происходит вся магия. Если упрощенно - получаем определенный список сборок (Assembly), забираем оттуда определенные типы (GetExportedTypes плюс немного фильтрации) и получаем искомые пространства имен и пихаем в this.NamespaceImports.

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

Возник небольшой затык с design-time, во время работы с представлением в проекте Web в Visual Studio.
Во-первых, пришлось подписывать библиотеку Core строгим именем и регистрировать в GAC, иначе в designtime студия не видит Core и соответственно не видит тип CustomWebRazorHostFactory.
Во-вторых, в designtime в AppDomain в VisualStudio находится только сборка Core. Попробую разъяснить.
Если запустить студию и открыть все решение (solution), затем открыть еще одну копию студии и подцепиться к первой отладчиком ("Attach to process"), то можно отследить, что происходит внутри GetEngineNamespaces в момент открытия представления в редакторе студии. Ну, я и прослеживаю. AppDomain содержит примерно 500 загруженных сборок, это всё - сборки самой студии, расширения, сторонние компоненты и прочее. Плюс там есть загруженная сборка Core, т.к. GetEngineNamespaces вызывается внутри неё. НО! Кроме Core, есть еще ряд типов внутри Web, пространства имен которых мне надо отразить в NamespacesImport. Но сборки Web нет в AppDomain студии, т.к. это открытая в Solution сборка.

Итак, вопрос дня - каким образом можно дотянуться до какого-то контекста внутри студии, чтобы вытащить оттуда те же типы и пространства имен, которые, условно говоря, видит Intellisense внутри Web?

P.S. Если иметь ТРи проекта, Core, WebAdditional и Web, подключить WebAdditional и Core внутрь Web, то в designtime представления в Web будет опять же только Core, но мне надо и WebAdditional увидеть.
  • Вопрос задан
  • 123 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы