/// <summary> /// 添加字段 /// </summary> /// <param name="field">字段信息</param> /// <param name="attribute">XML序列化成员配置</param> public void Push(FieldIndex field, MemberAttribute attribute) { Label end = generator.DefineLabel(); generator.memberMapIsMember(OpCodes.Ldarg_0, field.MemberIndex); generator.Emit(OpCodes.Brfalse, end); MethodInfo isOutputMethod = SerializeMethodCache.GetIsOutputMethod(field.Member.FieldType); if (isOutputMethod != null) { generator.Emit(OpCodes.Ldarg_1); if (isValueType) { generator.Emit(OpCodes.Ldarga_S, 2); } else { generator.Emit(OpCodes.Ldarg_2); } generator.Emit(OpCodes.Ldfld, field.Member); generator.call(isOutputMethod); generator.Emit(OpCodes.Brfalse, end); } string name = field.AnonymousName; SerializeMemberDynamicMethod.WriteName(generator, OpCodes.Ldloc_0, name, false); if (attribute != null && attribute.ItemName != null) { generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldstr, attribute.ItemName); generator.Emit(OpCodes.Stfld, SerializeMemberDynamicMethod.ItemNameField); } bool isCustom = false; MethodInfo method = SerializeMethodCache.GetMemberMethodInfo(field.Member.FieldType, ref isCustom); if (isCustom) { if (isValueType) { generator.Emit(OpCodes.Ldarga_S, 2); } else { generator.Emit(OpCodes.Ldarg_2); } generator.Emit(OpCodes.Ldflda, field.Member); generator.Emit(OpCodes.Ldarg_1); } else { generator.Emit(OpCodes.Ldarg_1); if (isValueType) { generator.Emit(OpCodes.Ldarga_S, 2); } else { generator.Emit(OpCodes.Ldarg_2); } generator.Emit(OpCodes.Ldfld, field.Member); } generator.call(method); SerializeMemberDynamicMethod.WriteName(generator, OpCodes.Ldloc_0, name, true); generator.MarkLabel(end); }
static TypeSerializer() { Type type = typeof(valueType); MethodInfo methodInfo = XmlSerializer.GetSerializeMethod(type); if (methodInfo != null) { defaultSerializer = (Action <XmlSerializer, valueType>)Delegate.CreateDelegate(typeof(Action <XmlSerializer, valueType>), methodInfo); isValueType = true; return; } if (type.IsArray) { if (type.GetArrayRank() == 1) { defaultSerializer = (Action <XmlSerializer, valueType>)SerializeMethodCache.GetArray(type.GetElementType()); } else { defaultSerializer = ignore; } isValueType = true; return; } if (type.IsEnum) { defaultSerializer = enumToString; isValueType = true; return; } if (type.IsInterface || type.IsPointer || typeof(Delegate).IsAssignableFrom(type)) { defaultSerializer = ignore; isValueType = true; return; } if (type.IsGenericType) { Type genericType = type.GetGenericTypeDefinition(); if (genericType == typeof(Nullable <>)) { defaultSerializer = (Action <XmlSerializer, valueType>)StructGenericType.Get(type.GetGenericArguments()[0]).XmlSerializeNullableMethod; isValueType = true; return; } } if ((methodInfo = SerializeMethodCache.GetCustom(type)) != null) { if (type.IsValueType) { #if NOJIT defaultSerializer = new CustomSerializer(methodInfo).Serialize; #else DynamicMethod dynamicMethod = new DynamicMethod("CustomXmlSerializer", null, new Type[] { typeof(XmlSerializer), type }, type, true); ILGenerator generator = dynamicMethod.GetILGenerator(); generator.Emit(OpCodes.Ldarga_S, 1); generator.Emit(OpCodes.Ldarg_0); generator.call(methodInfo); generator.Emit(OpCodes.Ret); defaultSerializer = (Action <XmlSerializer, valueType>)dynamicMethod.CreateDelegate(typeof(Action <XmlSerializer, valueType>)); #endif } else { defaultSerializer = (Action <XmlSerializer, valueType>)Delegate.CreateDelegate(typeof(Action <XmlSerializer, valueType>), methodInfo); } isValueType = true; } else { Delegate enumerableDelegate = SerializeMethodCache.GetIEnumerable(type); if (enumerableDelegate != null) { defaultSerializer = (Action <XmlSerializer, valueType>)enumerableDelegate; isValueType = true; } else { Type attributeType; attribute = type.customAttribute <XmlSerializeAttribute>(out attributeType) ?? (type.Name[0] == '<' ? XmlSerializeAttribute.AnonymousTypeMember : XmlSerializer.DefaultAttribute); if (type.IsValueType) { isValueType = true; } else if (attribute != XmlSerializer.DefaultAttribute && attributeType != type) { for (Type baseType = type.BaseType; baseType != typeof(object); baseType = baseType.BaseType) { XmlSerializeAttribute baseAttribute = baseType.customAttribute <XmlSerializeAttribute>(); if (baseAttribute != null) { if (baseAttribute.IsBaseType) { methodInfo = SerializeMethodCache.BaseSerializeMethod.MakeGenericMethod(baseType, type); defaultSerializer = (Action <XmlSerializer, valueType>)Delegate.CreateDelegate(typeof(Action <XmlSerializer, valueType>), methodInfo); return; } break; } } } LeftArray <KeyValue <FieldIndex, XmlSerializeMemberAttribute> > fields = SerializeMethodCache.GetFields(MemberIndexGroup <valueType> .GetFields(attribute.MemberFilters), attribute); LeftArray <PropertyMethod> properties = SerializeMethodCache.GetProperties(MemberIndexGroup <valueType> .GetProperties(attribute.MemberFilters), attribute); bool isBox = false; if (type.IsValueType && fields.Length + properties.Length == 1) { BoxSerializeAttribute boxSerialize = AutoCSer.Metadata.TypeAttribute.GetAttribute <BoxSerializeAttribute>(type); if (boxSerialize != null && boxSerialize.IsXml) { isBox = true; } } #if NOJIT if (isBox) { defaultSerializer = memberSerializer = new FieldPropertySerializer(ref fields, ref properties).SerializeBox; } else { memberSerializer = new FieldPropertySerializer(ref fields, ref properties).Serialize; memberMapSerializer = new MemberMapSerializer(ref fields, ref properties).Serialize; } #else SerializeMemberDynamicMethod dynamicMethod = new SerializeMemberDynamicMethod(type); SerializeMemberMapDynamicMethod memberMapDynamicMethod = isBox ? default(SerializeMemberMapDynamicMethod) : new SerializeMemberMapDynamicMethod(type); foreach (KeyValue <FieldIndex, XmlSerializeMemberAttribute> member in fields) { if (isBox) { dynamicMethod.PushBox(member.Key); } else { dynamicMethod.Push(member.Key, member.Value); memberMapDynamicMethod.Push(member.Key, member.Value); } } foreach (PropertyMethod member in properties) { if (isBox) { dynamicMethod.PushBox(member.Property, member.Method); } else { dynamicMethod.Push(member.Property, member.Method, member.Attribute); memberMapDynamicMethod.Push(member.Property, member.Method, member.Attribute); } } memberSerializer = (Action <XmlSerializer, valueType>)dynamicMethod.Create <Action <XmlSerializer, valueType> >(); if (isBox) { defaultSerializer = memberSerializer; } else { memberMapSerializer = (Action <MemberMap, XmlSerializer, valueType>)memberMapDynamicMethod.Create <Action <MemberMap, XmlSerializer, valueType> >(); } #endif } } }
/// <summary> /// 添加属性 /// </summary> /// <param name="property">属性信息</param> /// <param name="propertyMethod">函数信息</param> /// <param name="attribute">XML序列化成员配置</param> public void Push(PropertyIndex property, MethodInfo propertyMethod, MemberAttribute attribute) { Label end = generator.DefineLabel(); generator.memberMapIsMember(OpCodes.Ldarg_0, property.MemberIndex); generator.Emit(OpCodes.Brfalse, end); MethodInfo isOutputMethod = SerializeMethodCache.GetIsOutputMethod(property.Member.PropertyType); if (isOutputMethod != null) { generator.Emit(OpCodes.Ldarg_1); if (isValueType) { generator.Emit(OpCodes.Ldarga_S, 2); } else { generator.Emit(OpCodes.Ldarg_2); } generator.call(propertyMethod); generator.call(isOutputMethod); generator.Emit(OpCodes.Brfalse, end); } SerializeMemberDynamicMethod.WriteName(generator, OpCodes.Ldloc_0, property.Member.Name, false); if (attribute != null && attribute.ItemName != null) { generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldstr, attribute.ItemName); generator.Emit(OpCodes.Stfld, SerializeMemberDynamicMethod.ItemNameField); } bool isCustom = false; MethodInfo method = SerializeMethodCache.GetMemberMethodInfo(property.Member.PropertyType, ref isCustom); if (isCustom) { LocalBuilder loadMember = generator.DeclareLocal(property.Member.PropertyType); if (isValueType) { generator.Emit(OpCodes.Ldarga_S, 2); } else { generator.Emit(OpCodes.Ldarg_2); } generator.call(propertyMethod); generator.Emit(OpCodes.Stloc_0); generator.Emit(OpCodes.Ldloca_S, loadMember); generator.Emit(OpCodes.Ldarg_1); } else { generator.Emit(OpCodes.Ldarg_1); if (isValueType) { generator.Emit(OpCodes.Ldarga_S, 2); } else { generator.Emit(OpCodes.Ldarg_2); } generator.call(propertyMethod); } generator.call(method); SerializeMemberDynamicMethod.WriteName(generator, OpCodes.Ldloc_0, property.Member.Name, true); generator.MarkLabel(end); }