2016-11-22 6 views
0

В настоящее время я реализую схему разрешения имен типов. Имеющаяся информация очень похожа на то, что вы получите в обычном проекте C# источника:Разрешение динамического типа - множественные вызовы Type.GetType или сканирование всех типов в сборке?

  • список Assembly ссылка
  • список using пространств имен

Во время выполнения для каждого имени типа для разрешения имя имеет либо полную квалификацию (с пространством имен, но не с именем сборки), либо это простое имя, которое ожидается из одного из пространств имен using.

Для того, чтобы найти Type соответствие каждого идентификатора, я рассматриваю один из двух стратегий:

  1. Preload все сборки с помощью Assembly.Load и сканирования всех типов. Все простые имена, которые имеют префикс пространства имен, соответствующий одному из пространств имен using, будут заблокированы. Также создается словарь для сопоставления каждого имени типа именного типа в сборке непосредственно с его Type. Разрешение конфликтов будет выполняться соответственно во время фазы загрузки.

  2. Не загружайте ничего. В случае прибытия типа типа попробуйте выполнить следующую последовательность:

    • Предположите, что имя полностью квалифицировано; объедините каждое из названных имен узлов в свою очередь, чтобы создать имя, соответствующее сборке, и вызовите Type.GetType, чтобы узнать, получим ли мы действительный тип.

    • Если приведенный выше шаг не приводит к допустимому типу и имя не имеет префикса, предположим, что это простое имя; повторите вышеуказанный шаг, но каждый раз добавляйте простое имя к одному из пространств имен using, чтобы узнать, получим ли мы действительный тип.

Какой подход был бы предпочтительнее, и какие плюсы и минусы?

Пока неясно, сколько типов необходимо будет разрешить таким образом для каждого прогона, но я принимаю что-либо между 10 и 100. Множество сборок можно ссылаться в любой точке, каждая из которых имеет потенциально сотни типов ,

Мне интересно узнать относительные характеристики обеих стратегий и любопытно узнать о существующих передовых методах борьбы с этим сценарием. В дополнение к производительности, было бы очень полезно понять любую разницу в поведенческих побочных эффектах: например, сканирует ли все типы в Assembly все статические конструкторы для загружаемых типов? Я предпочел бы подход, который был бы настолько ленив, насколько это возможно, при запуске любого кода из ссылочных сборок.

+0

Я считаю, что это [проблема XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy -problem). Было бы более полезно, если бы вы объяснили, что вы пытаетесь достичь этого, потому что, может быть, вы пытаетесь заново изобрести квадратное колесо. Или кто знает. Сообщите нам, что является требованием вашей проблемы. –

+0

@ MatíasFidemraizer Я рассматриваю стратегию разрешения динамического типа для языка сценариев и хотел бы быть более комфортным с возможными стратегиями для сопоставления имен типам и их значениям. Ни в коем случае я не хотел подразумевать, что у меня было решение проблемы, но я действительно хотел перечислить подходы, которые пришли мне на ум. Было бы здорово узнать о любых других возможностях. – glopes

+0

Вы создаете скриптовый язык? –

ответ

0

В новом стандарте .NET оказывается, что есть намного лучший способ сделать это, используя новое пространство имен System.Reflection.Metadata. По их собственным словам:

«Эти пакеты предоставляют читатель метаданных низкого уровня .NET (ECMA-335).

Он ориентирован на производительность и является идеальным выбором для построения библиотеки более высокого уровня, которые намерены обеспечить свою собственную объектную модель, , такие как компиляторы.»

Вот небольшой фрагмент кода для перечисления имени и пространство имен для всех определений типов в данном сборочном файле:

using System; 
using System.IO; 
using System.Reflection.Metadata; 
using System.Reflection.PortableExecutable; 

namespace MetadataTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var stream = File.OpenRead(args[0])) 
      using (var peFile = new PEReader(stream)) 
      { 
       var metadataReader = peFile.GetMetadataReader(); 
       foreach (var type in metadataReader.TypeDefinitions) 
       { 
        var definition = metadataReader.GetTypeDefinition(type); 
        var name = metadataReader.GetString(definition.Name); 
        var ns = metadataReader.GetString(definition.Namespace); 
        Console.WriteLine(ns + "." + name); 
       } 
      } 
     } 
    } 
}