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); } }
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); } }
/// <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() }); }
/// <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); }