Как получить дискриминатор типов для класса?

В MDriven я хотел бы получить дискриминатор типов для смоделированного класса во время выполнения. Я думал, что делал это раньше, но не могу найти и не могу понять.

Я имею в виду целое число, которое появляется первым в строке внешнего идентификатора, например. "72" во внешнем идентификаторе "72!i64!12345678".

Мне нужно получить дискриминатор на основе типа С#, то есть typeof(MyClass), не имея доступного экземпляра объекта. Это делает невозможным извлечение дискриминатора из строки внешнего идентификатора, потому что у меня нет такой строки в то время и я не могу ее создать.

Я использую Eco.Services.Impl.ExternalIdServiceImpl_DbType, поэтому дискриминатор типа внешнего идентификатора соответствует дискриминатору типа в базе данных, если это имеет значение. Но как найти дискриминатор типа во время выполнения?


person Kjell Rilbe    schedule 12.09.2019    source источник
comment
@CodingYoshi: Нет, пожалуйста, прочитайте мое разъяснение. Цель состоит в том, чтобы создать строку внешнего идентификатора из числового идентификационного номера, идентификатора типа i64 (известного) и номера дискриминатора, который мне нужно как-то найти.   -  person Kjell Rilbe    schedule 12.09.2019


Ответы (2)


Найдя исходный код для Eco.Services.Impl.ExternalIdServiceImpl_DbType, я смог создать это решение:

public static string GetClassDiscriminator<T>(this IEcoServiceProvider sp)
{
    IEcoTypeSystem typeSys = sp.GetEcoService<ITypeSystemService>().TypeSystem;
    IClass cls = typeSys.AllClasses.Cast<IClass>().First(c => c.ObjectType == typeof(T));
    if (sp.GetEcoService<IExternalIdService>() is Eco.Services.Impl.ExternalIdServiceImpl_DbType)
    {
        ORMappingDefinition mapping = ((PersistenceMapperDb)DiamondsPMP.Instance.PersistenceMapper).EffectiveRunTimeMappingProvider.Mapping;
        if (mapping == null)
            throw new InvalidOperationException(PersistenceStringRes.MappingProviderNotInitialized);
        ClassDefinition classdef = mapping.Classes[typeSys.AllClasses[0].Name];
        if (classdef.Discriminators.Count == 0)
            throw new InvalidOperationException(PersistenceStringRes.RootclassHasNoDiscriminatorDefined);
        DiscriminatorDef discriminator = classdef.Discriminators.Cast<DiscriminatorDef>().First();
        DiscriminatorValue discvalue = discriminator.DiscriminatorValuesByClassId(cls.InternalIndex);
        if (discvalue == null)
            throw new InvalidOperationException(PersistenceStringRes.ClassHasNoDiscriminatorValueDefined);
        if (discvalue.IsFinal && cls.SubTypes.Count > 0)
            throw new InvalidOperationException(PersistenceStringRes.DiscriminatorIsFinal);
        return discvalue.Value;
    }
    else
        return cls.InternalIndex.ToString();
}

В моем случае требуется sp.GetEcoService<IExternalIdService>() is Eco.Services.Impl.ExternalIdServiceImpl_DbType, потому что в своих модульных тестах я использую PersistenceMapperMemory, который использует индекс в TypeSystem.AllClasses в качестве дискриминатора типов, который также является значением, возвращаемым IClass.InternalIndex.

Также отмечу, что IExternalIdService.ObjectForIdSeperateClassInfo() глючит. Он действует так, как будто используется Eco.Services.Impl.ExternalIdServiceImpl, возвращая IObjectInstance неправильного типа (используя индекс класса в TypeSystem.AllClasses).

person Kjell Rilbe    schedule 10.12.2019
comment
Отлично копать! Я исправлю проблему с ObjectForIdSeperateClassInfo при использовании службы ExternalIdServiceImpl_DbType. Теперь он переопределен для использования правильного значения дискриминатора на основе базы данных. - person Hans Karlsen; 12.12.2019

Дискриминатор 72 также является индексом в списке классов TypeService.

IClass umlClass = (IClass)TypeSystem.AllClasses[72];
person Hans Karlsen    schedule 15.09.2019
comment
Примечание. Новые сборки поддерживают добавление имени дескриптора вместо номера при отправке удостоверений: TheRealClassName!i64!12345678 Это более надежно для моделей, которые меняются (все модели меняются), по крайней мере, если номер хранится третьей стороной. - person Hans Karlsen; 15.09.2019
comment
В моем случае я пытаюсь построить строку externalid, поэтому мне скорее нужно обратное: TypeSystem.AllClasses.IndexOf(umlClass). - person Kjell Rilbe; 16.09.2019
comment
Кроме того, это будет TheCSharpClassName!i64!12345678 или ModeledClassName!i64!12345678? - person Kjell Rilbe; 16.09.2019
comment
@KjellRilbe — имя c#, которое мы называем RuntimeName - person Hans Karlsen; 17.09.2019
comment
Ваш ответ действителен для Eco.Services.Impl.ExternalIdServiceImpl_DbType? - person Kjell Rilbe; 18.09.2019
comment
Для большинства практических целей да - если у вас есть расширенные реализации ORMapping, у вас может быть несколько значений дискриминатора в одном классе - это сместит дискриминатор БД по индексу класса - person Hans Karlsen; 20.09.2019
comment
Подняв этот поток, пытаясь sp.GetEcoService<ITypeSystemService>().TypeSystem.AllClasses[17].ModeledName, потому что ECO_TYPE = 17 в базе данных, я не получаю класс, который хочу. Я получаю совершенно другое. У меня нет расширенных сопоставлений, но у меня есть два пакета (поставщик ASP + мои собственные материалы). Какие-либо предложения? - person Kjell Rilbe; 09.12.2019
comment
Извлечение всех записей из TypeSystem, а также из таблицы ECO_TYPE не показывает никакой корреляции между значениями ECO_TYPE, используемыми Eco.Services.Impl.ExternalIdServiceImpl_DbType, и индексами в TypeSystem. Насколько я понимаю, ваш ответ просто неверен для Eco.Services.Impl.ExternalIdServiceImpl_DbType. Мой вопрос остается без ответа. - person Kjell Rilbe; 09.12.2019
comment
Кстати, TypeSystem.AllClasses — это ICollection, который не поддерживает IndexOf(). На самом деле, если индексы элементов имеют какое-либо значение, это, вероятно, должно быть IList, а не ICollection. Коллекции предназначены для неупорядоченных коллекций элементов. - person Kjell Rilbe; 09.12.2019
comment
@KjellRilbe - это будет Name==RuntimeName, а не ModelName (которое может содержать национальные символы) - person Hans Karlsen; 12.12.2019