public static UnionSerializationInfo Create(Type type, Type resolverType, TypeBuilder typeBuilder, Microsoft.FSharp.Reflection.UnionCaseInfo caseInfo) { var ti = type.GetTypeInfo(); var members = new List <EmittableMember>(); foreach (var item in caseInfo.GetFields()) { var field = typeBuilder.DefineField("<>" + item.Name + item.Name + "Formatter", typeof(Formatter <,>).MakeGenericType(resolverType, item.PropertyType), FieldAttributes.Private | FieldAttributes.InitOnly); var member = new EmittableMember { PropertyInfo = item, Formatter = field }; members.Add(member); } MethodInfo method; var methodParameters = new List <EmittableMember>(); if (caseInfo.GetFields().Any()) { method = ti.GetMethod("New" + caseInfo.Name, BindingFlags.Static | BindingFlags.Public); } else { method = ti.GetProperty(caseInfo.Name, BindingFlags.Public | BindingFlags.Static).GetGetMethod(); } return(new UnionSerializationInfo { Tag = caseInfo.Tag, NewMethod = method, Members = members.ToArray() }); }
public static UnionSerializationInfo CreateOrNull(Type type, Microsoft.FSharp.Reflection.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() }); }