如何获得 class 的类型鉴别器?

How to get type discriminator for class?

在 MDriven 中,我想在运行时获取建模 class 的类型鉴别器。我以为我以前做过,但是好像找不到,想不通。

我的意思是在外部 id 字符串中最先出现的整数,例如外部 ID“72!i64!12345678”中的“72”。

我需要获得基于 C# 类型的鉴别器,即 typeof(MyClass),但没有任何可用的对象实例。这使得无法从外部 id 字符串中提取鉴别器,因为我当时没有可用的字符串并且无法创建一个。

我正在使用 Eco.Services.Impl.ExternalIdServiceImpl_DbType,因此外部 ID 的类型鉴别器与数据库中的类型鉴别器相匹配,以防万一。但是如何在运行时查找类型的鉴别器?

判别器72也是类的TypeService列表中的索引。

IClass umlClass = (IClass)TypeSystem.AllClasses[72];

找到 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 中的 class' 索引)。