Пример #1
0
 public ErasedUnionConverter(UnionCaseInfo info, PropertyInfo[] props)
 {
     _props         = props;
     _isSingleValue = IsSingleValueCase(props);
     _isTupleValue  = IsTupleCase(props);
     _toCase        = FSharpValue.PreComputeUnionConstructor(info, FSharpOption <BindingFlags> .None);
     _fromCase      = FSharpValue.PreComputeUnionReader(info, FSharpOption <BindingFlags> .None);
     if (_isTupleValue)
     {
         _tupleType = MakeTupleType(props);
         _toTuple   = FSharpValue.PreComputeTupleConstructor(_tupleType);
         _fromTuple = FSharpValue.PreComputeTupleReader(_tupleType);
     }
 }
Пример #2
0
 public CaseData(UnionCaseInfo info, PropertyInfo[] props)
 {
     Name         = info.Name;
     Props        = props;
     ToCase       = FSharpValue.PreComputeUnionConstructor(info, FSharpOption <BindingFlags> .None);
     FromCase     = FSharpValue.PreComputeUnionReader(info, FSharpOption <BindingFlags> .None);
     IsEmpty      = props.Length == 0;
     IsSingleCase = IsSingleValueCase(props);
     if (IsTupleCase(props))
     {
         TupleType = MakeTupleType(props);
         ToTuple   = FSharpValue.PreComputeTupleConstructor(TupleType);
         FromTuple = FSharpValue.PreComputeTupleReader(TupleType);
     }
 }
Пример #3
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="info"></param>
        /// <returns></returns>
        public static T GetCustomAttribute <T>(this UnionCaseInfo info)
            where T : Attribute
        {
            if (_unioncaseinfoCache.TryGetValue(info, out Attribute cache) && cache is T)
            {
                return((T)cache);
            }

            if (info.GetCustomAttributes(typeof(T)).FirstOrDefault() is T attribute)
            {
                _unioncaseinfoCache.Add(info, attribute);
                return(attribute);
            }
            else
            {
                return(null);
            }
        }
        public static UnionSerializationInfo CreateOrNull(Type type, UnionCaseInfo caseInfo)
        {
            type = caseInfo.DeclaringType;

            var ti      = type.GetTypeInfo();
            var isClass = ti.IsClass;

            var contractAttr = ti.GetCustomAttribute <MessagePackObjectAttribute>();

            var isIntKey      = true;
            var intMembers    = new Dictionary <int, EmittableMember>();
            var stringMembers = new Dictionary <string, EmittableMember>();

            if (contractAttr == null || contractAttr.KeyAsPropertyName)
            {
                isIntKey = false;

                var hiddenIntKey = 0;
                foreach (var item in caseInfo.GetFields())
                {
                    var member = new EmittableMember
                    {
                        PropertyInfo = item,
                        StringKey    = item.Name,
                        IntKey       = hiddenIntKey++
                    };
                    stringMembers.Add(member.StringKey, member);
                }
            }
            else
            {
                var hiddenIntKey = 0;
                foreach (var item in caseInfo.GetFields())
                {
                    var member = new EmittableMember
                    {
                        PropertyInfo = item,
                        IntKey       = hiddenIntKey++
                    };
                    intMembers.Add(member.IntKey, member);
                }
            }

            MethodInfo method;
            var        methodParameters = new List <EmittableMember>();

            if (caseInfo.GetFields().Any())
            {
                method = ti.GetMethod("New" + caseInfo.Name, BindingFlags.Static | BindingFlags.Public);
                if (method == null)
                {
                    throw new MessagePackDynamicUnionResolverException("can't find public method. case:" + caseInfo.Name);
                }

                var methodLookupDictionary = stringMembers.ToLookup(x => x.Key, x => x, StringComparer.OrdinalIgnoreCase);

                var methodParamIndex = 0;
                foreach (var item in method.GetParameters())
                {
                    EmittableMember paramMember;
                    if (isIntKey)
                    {
                        if (intMembers.TryGetValue(methodParamIndex, out paramMember))
                        {
                            if (item.ParameterType == paramMember.Type)
                            {
                                methodParameters.Add(paramMember);
                            }
                            else
                            {
                                throw new MessagePackDynamicUnionResolverException("can't find matched method parameter, parameterType mismatch. case:" + caseInfo.Name + " parameterIndex:" + methodParamIndex + " paramterType:" + item.ParameterType.Name);
                            }
                        }
                        else
                        {
                            throw new MessagePackDynamicUnionResolverException("can't find matched method parameter, index not found. case:" + caseInfo.Name + " parameterIndex:" + methodParamIndex);
                        }
                    }
                    else
                    {
                        var hasKey = methodLookupDictionary[item.Name];
                        var len    = hasKey.Count();
                        if (len != 0)
                        {
                            if (len != 1)
                            {
                                throw new MessagePackDynamicUnionResolverException("duplicate matched method parameter name:" + caseInfo.Name + " parameterName:" + item.Name + " paramterType:" + item.ParameterType.Name);
                            }

                            paramMember = hasKey.First().Value;
                            if (item.ParameterType == paramMember.Type)
                            {
                                methodParameters.Add(paramMember);
                            }
                            else
                            {
                                throw new MessagePackDynamicUnionResolverException("can't find matched method parameter, parameterType mismatch. case:" + caseInfo.Name + " parameterName:" + item.Name + " paramterType:" + item.ParameterType.Name);
                            }
                        }
                        else
                        {
                            throw new MessagePackDynamicUnionResolverException("can't find matched method parameter, index not found. case:" + caseInfo.Name + " parameterName:" + item.Name);
                        }
                    }
                    methodParamIndex++;
                }
            }
            else
            {
                method = ti.GetProperty(caseInfo.Name, BindingFlags.Public | BindingFlags.Static).GetGetMethod();
            }

            return(new UnionSerializationInfo
            {
                IsClass = isClass,
                NewMethod = method,
                MethodParameters = methodParameters.ToArray(),
                IsIntKey = isIntKey,
                Members = (isIntKey) ? intMembers.Values.ToArray() : stringMembers.Values.ToArray()
            });
        }
Пример #5
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="info"></param>
 /// <param name="attribute"></param>
 /// <returns></returns>
 public static bool TryGetCustomAttribute <T>(this UnionCaseInfo info, out T attribute)
     where T : Attribute
 {
     attribute = info.GetCustomAttribute <T>();
     return(attribute != null);
 }