ограничение неуправляемого универсального параметра в IL

Когда я компилирую следующий код:

type Class1<'T when 'T : unmanaged> =
    class end

type Class2<'T> =
    class end

в ИЛ это выглядит так:

.class auto ansi serializable nested public Class1`1<T> extends [mscorlib]System.Object

.class auto ansi serializable nested public Class2`1<T> extends [mscorlib]System.Object

Где-то сохранено ограничение unmanaged? Если да, то где и как я могу получить его программно?

В этом вопросе я прочитал, что он находится где-то во "встроенном файле подписи" . Что это?


person IS4    schedule 02.04.2015    source источник
comment
возможный дубликат Поведение ограничения неуправляемого типа F#   -  person thehennyy    schedule 03.04.2015
comment
@thehennyy Этот вопрос в основном касается поведения и не полностью отвечает на мою проблему.   -  person IS4    schedule 03.04.2015
comment
В этом ответе более подробно рассматриваются встроенные данные подписи/оптимизации.   -  person kvb    schedule 04.04.2015
comment
@kvb Да, я сейчас изучаю это.   -  person IS4    schedule 04.04.2015
comment
@Hans На самом деле параметр не влияет на тип или ограничения. Ограничения хранятся в ресурсе, расположенном в сборке. К счастью, уже есть библиотека для интерпретации этого, см. мой ответ.   -  person IS4    schedule 05.04.2015


Ответы (1)


Эти ограничения расположены в данных объекта, хранящихся в управляемом ресурсе FSharpSignatureData. Их можно просматривать с помощью средства чтения метаданных F# из F# PowerPack:

public static IList<FSharpGenericParameterConstraint> GetFSharpGenericParameterConstraints(Type genericType, int position)
{
    return GetFSharpGenericParameterConstraints(genericType.GetGenericArguments()[position]);
}

public static IList<FSharpGenericParameterConstraint> GetFSharpGenericParameterConstraints(Type genericParameter)
{
    var declMethod = genericParameter.DeclaringMethod;
    var declType = genericParameter.DeclaringType;
    var fsAsm = FSharpAssembly.FromAssembly(genericParameter.Assembly);
    int pos = genericParameter.GenericParameterPosition;
    var entities = AllEntities(fsAsm.Entities);
    if(declMethod != null)
    {
        var member = entities.SelectMany(e => e.MembersOrValues).First(m => m.ReflectionMemberInfo == declMethod);
        return member.GenericParameters[pos].Constraints;
    }else if(declType != null)
    {
        var entity = entities.First(e => e.ReflectionType == declType);
        return entity.GenericParameters[pos].Constraints;
    }
    return null;
}

private static IEnumerable<FSharpEntity> AllEntities(IEnumerable<FSharpEntity> entities)
{
    return entities.Concat(entities.SelectMany(e => AllEntities(e.NestedEntities)));
}

bool unmanaged = GetFSharpGenericParameterConstraints(typeof(MyModule.Class1<>), 0).Any(c => c.IsUnmanagedConstraint);
person IS4    schedule 04.04.2015