Получить тип из GUID - PullRequest
       14

Получить тип из GUID

12 голосов
/ 12 января 2010

По разным причинам мне нужно реализовать механизм кэширования типов в C #. К счастью, CLR предоставляет Type.GUID для уникальной идентификации типа. К сожалению, я не могу найти способ найти тип, основанный на этом GUID. Есть Type.GetTypeFromCLSID(), но, основываясь на моем понимании документации (и экспериментов), она делает что-то совсем другое.

Есть ли способ получить тип, основанный на его GUID, за исключением циклического перебора всех загруженных типов и сравнения с их GUID?

РЕДАКТИРОВАТЬ : Я забыл упомянуть, что мне действительно нужен «отпечаток пальца» фиксированной ширины, поэтому GUID так мне нравится. В общем случае, конечно, будет работать полное имя типа.

Ответы [ 7 ]

7 голосов
/ 12 января 2010

почему бы не использовать назначенное свойство для этого, т.е. AssemblyQualifiedName ? Это свойство задокументировано как «может быть сохранено и позже использовано для загрузки Типа».

GUID для COM-взаимодействия.

4 голосов
/ 06 мая 2011

Это может быть просто краткое изложение уже опубликованных ответов, но я не думаю, что есть способ сделать это без предварительного построения карты Guid-> Type.

Мы делаем это в наших рамках при инициализации:

static TypeManager()
    {
        AppDomain.CurrentDomain.AssemblyLoad += (s, e) =>
        {
            _ScanAssembly(e.LoadedAssembly);
        };

        foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
        {
            _ScanAssembly(a);
        }
    }

    private static void _ScanAssembly(Assembly a)
    {
        foreach (Type t in a.GetTypes())
        {
           //optional check to filter types (by interface or attribute, etc.)
           //Add type to type map   
        }
    }

Обработка события AssemblyLoad заботится о динамически загружаемых сборках.

Насколько я понимаю, Type.GUID использует версию сборки типа как часть алгоритма генерации Guid. Это может привести к проблемам при увеличении номеров версий сборки. Возможно, было бы целесообразно использовать метод GetDeterministicGuid, описанный в другом ответе, в зависимости от вашего приложения.

3 голосов
/ 12 января 2010

Не зацикливаться на сравнении. Заполните Dictionary<Type> и используйте метод Contains.

Dictionary<Type> types = new Dictionary<Types>();
... //populate 

if (types.Contains(someObject.GetType())) 
  //do something

Это, безусловно, даст вам запись фиксированного размера, поскольку все они будут ссылками на объекты (экземпляры Type по существу являются объектами фабрики).

1 голос
/ 12 января 2010

Как насчет (из Генерация детерминированных GUID ):

private Guid GetDeterministicGuid(string input)
{
    // use MD5 hash to get a 16-byte hash of the string:
    MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
    byte[] inputBytes = Encoding.Default.GetBytes(input);
    byte[] hashBytes = provider.ComputeHash(inputBytes);

    // generate a guid from the hash:
    Guid hashGuid = new Guid(hashBytes);
    return hashGuid;
}

И добавь это typeof().AssemblyQualifiedName. Вы можете хранить эти данные в коллекции Dictionary<string, Guid> (или, что угодно, <Guid, string>).

Таким образом, у вас всегда будет один и тот же GUID для данного типа (предупреждение: возможен конфликт).

0 голосов
/ 03 марта 2016

Я бы использовал typeof (class) .GUID, чтобы найти экземпляр в словаре кеша:

private Dictionary<Guid, class> cacheDictionary { get; set; }

и у меня будет метод для возврата словаря и GUID в качестве параметра метода для поиска класса в словаре.

public T Getclass<T>()
    {
        var key = typeof(T).GUID;
        var foundClass= cacheDictionary.FirstOrDefault(x => x.Key == key);
        T item;
        if (foundClass.Equals(default(KeyValuePair<Guid, T>)))
        {
            item = new T()
            cacheDictionary.Add(key, item);
        }
        else
            item = result.Value;

        return item;
    }

и я бы использовал одноэлементный шаблон для кэша,

и вызов будет выглядеть примерно так:

   var cachedObject = Cache.Instance.Getclass<class>();
0 голосов
/ 12 января 2010

Документация Mono сообщает, что модуль имеет кучу метаданных направляющих .

Возможно Сесил может помочь вам найти тип, основанный на его guid? Хотя не уверен, что существует класс GuidHeap , он, кажется, генерирует направляющие, но, возможно, этого достаточно для работы вашего кэша?

0 голосов
/ 12 января 2010

Если вы контролируете эти классы, я бы порекомендовал:

public interface ICachable
{
    Guid ClassId { get; }
}

public class Person : ICachable
{
    public Guid ClassId
    {
        get {  return new Guid("DF9DD4A9-1396-4ddb-98D4-F8F143692C45"); }
    }
}

Вы можете сгенерировать GUID, используя Visual Studio, Инструменты-> Создать Guid.

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