/// <summary> /// Adds a known sub-type to the inheritance model /// </summary> public MetaType AddSubType(int fieldNumber, Type derivedType) { if (derivedType == null) throw new ArgumentNullException("derivedType"); if (fieldNumber < 1) throw new ArgumentOutOfRangeException("fieldNumber"); if (!(type.IsClass || type.IsInterface) || type.IsSealed) { throw new InvalidOperationException("Sub-types can only be added to non-sealed classes"); } if (typeof(IEnumerable).IsAssignableFrom(type)) { throw new ArgumentException("Repeated data (a list, collection, etc) has inbuilt behaviour and cannot be subclassed"); } if (typeof(IEnumerable).IsAssignableFrom(derivedType)) { throw new ArgumentException("Repeated data (a list, collection, etc) has inbuilt behaviour and cannot be used as a subclass"); } ThrowIfFrozen(); MetaType derivedMeta = model[derivedType]; derivedMeta.ThrowIfFrozen(); SubType subType = new SubType(fieldNumber, derivedMeta); ThrowIfFrozen(); derivedMeta.SetBaseType(this); // includes ThrowIfFrozen if (subTypes == null) subTypes = new BasicList(); subTypes.Add(subType); return this; }
public Group(int first) { this.First = first; this.Items = new BasicList(); }
private void CascadeDependents(BasicList list, MetaType metaType) { MetaType surrogateOrBaseOrSelf; if (metaType.IsList) { Type listItemType = TypeModel.GetListItemType(this, metaType.Type); if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, listItemType, out WireType _, asReference: false, dynamicType: false, overwriteList: false, allowComplexTypes: false) != null) { return; } int num = FindOrAddAuto(listItemType, demand: false, addWithContractOnly: false, addEvenIfAutoDisabled: false); if (num >= 0) { surrogateOrBaseOrSelf = ((MetaType)types[num]).GetSurrogateOrBaseOrSelf(deep: false); if (!list.Contains(surrogateOrBaseOrSelf)) { list.Add(surrogateOrBaseOrSelf); CascadeDependents(list, surrogateOrBaseOrSelf); } } return; } if (metaType.IsAutoTuple) { if (MetaType.ResolveTupleConstructor(metaType.Type, out MemberInfo[] mappedMembers) != null)
// Token: 0x06000371 RID: 881 RVA: 0x00012D84 File Offset: 0x00010F84 internal IProtoSerializer TryGetBasicTypeSerializer(Type type) { int num = this.basicTypes.IndexOf(RuntimeTypeModel.BasicTypeFinder, type); if (num >= 0) { return(((RuntimeTypeModel.BasicType) this.basicTypes[num]).Serializer); } BasicList obj = this.basicTypes; IProtoSerializer result; lock (obj) { num = this.basicTypes.IndexOf(RuntimeTypeModel.BasicTypeFinder, type); if (num >= 0) { result = ((RuntimeTypeModel.BasicType) this.basicTypes[num]).Serializer; } else { WireType wireType; IProtoSerializer protoSerializer = (MetaType.GetContractFamily(this, type, null) == MetaType.AttributeFamily.None) ? ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out wireType, false, false, false, false) : null; if (protoSerializer != null) { this.basicTypes.Add(new RuntimeTypeModel.BasicType(type, protoSerializer)); } result = protoSerializer; } } return(result); }
internal static BasicList GetContiguousGroups(int[] keys, object[] values) { if (keys == null) { throw new ArgumentNullException("keys"); } if (values == null) { throw new ArgumentNullException("values"); } if (values.Length < keys.Length) { throw new ArgumentException("Not all keys are covered by values", "values"); } BasicList outer = new BasicList(); Group group = null; for (int i = 0; i < keys.Length; i++) { if (i == 0 || keys[i] != keys[i - 1]) { group = null; } if (group == null) { group = new Group(keys[i]); outer.Add(group); } group.Items.Add(values[i]); } return(outer); }
private void CascadeDependents(BasicList list, MetaType metaType) { if (metaType.IsList) { Type listItemType = TypeModel.GetListItemType(this, metaType.Type); if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, listItemType, out WireType _, false, false, false, false) == null) { int num = FindOrAddAuto(listItemType, false, false, false); if (num >= 0) { MetaType surrogateOrBaseOrSelf = ((MetaType)types[num]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(surrogateOrBaseOrSelf)) { list.Add(surrogateOrBaseOrSelf); CascadeDependents(list, surrogateOrBaseOrSelf); } } } } else { MetaType surrogateOrBaseOrSelf; if (metaType.IsAutoTuple) { if (MetaType.ResolveTupleConstructor(metaType.Type, out MemberInfo[] array) != (ConstructorInfo)null)
/// <summary> /// Adds a known sub-type to the inheritance model /// </summary> public MetaType AddSubType(int fieldNumber, Type derivedType) { if (!(type.IsClass || type.IsInterface) || type.IsSealed) { throw new InvalidOperationException("Sub-types can only be added to non-sealed classes"); } if (typeof(IEnumerable).IsAssignableFrom(type)) { throw new ArgumentException("Repeated data (a list, collection, etc) has inbuilt behaviour and cannot be subclassed"); } ThrowIfFrozen(); MetaType derivedMeta = model[derivedType]; derivedMeta.ThrowIfFrozen(); SubType subType = new SubType(fieldNumber, derivedMeta); ThrowIfFrozen(); derivedMeta.SetBaseType(this); // includes ThrowIfFrozen if (subTypes == null) { subTypes = new BasicList(); } subTypes.Add(subType); return(this); }
private IProtoTypeSerializer BuildSerializer() { if (surrogate != null) { return(new SurrogateSerializer(type, model[surrogate].Serializer)); } fields.Trim(); int fieldCount = fields.Count; int subTypeCount = subTypes == null ? 0 : subTypes.Count; int[] fieldNumbers = new int[fieldCount + subTypeCount]; IProtoSerializer[] serializers = new IProtoSerializer[fieldCount + subTypeCount]; int i = 0; if (subTypeCount != 0) { foreach (SubType subType in subTypes) { fieldNumbers[i] = subType.FieldNumber; serializers[i++] = subType.Serializer; } } if (fieldCount != 0) { foreach (ValueMember member in fields) { fieldNumbers[i] = member.FieldNumber; serializers[i++] = member.Serializer; } } BasicList baseCtorCallbacks = null; MetaType tmp = BaseType; while (tmp != null) { MethodInfo method = tmp.HasCallbacks ? tmp.Callbacks.BeforeDeserialize : null; if (method != null) { if (baseCtorCallbacks == null) { baseCtorCallbacks = new BasicList(); } baseCtorCallbacks.Add(method); } tmp = tmp.BaseType; } MethodInfo[] arr = null; if (baseCtorCallbacks != null) { arr = new MethodInfo[baseCtorCallbacks.Count]; baseCtorCallbacks.CopyTo(arr, 0); Array.Reverse(arr); } return(new TypeSerializer(type, fieldNumbers, serializers, arr, baseType == null, useConstructor, callbacks)); }
static public int get_Count(IntPtr l) { try { ProtoBuf.Meta.BasicList self = (ProtoBuf.Meta.BasicList)checkSelf(l); pushValue(l, true); pushValue(l, self.Count); return(2); } catch (Exception e) { return(error(l, e)); } }
static public int Trim(IntPtr l) { try { ProtoBuf.Meta.BasicList self = (ProtoBuf.Meta.BasicList)checkSelf(l); self.Trim(); pushValue(l, true); return(1); } catch (Exception e) { return(error(l, e)); } }
static public int constructor(IntPtr l) { try { ProtoBuf.Meta.BasicList o; o = new ProtoBuf.Meta.BasicList(); pushValue(l, true); pushValue(l, o); return(2); } catch (Exception e) { return(error(l, e)); } }
/// <summary> /// Adds a known sub-type to the inheritance model /// </summary> public MetaType AddSubType(int fieldNumber, Type derivedType) { if (!type.IsClass || type.IsSealed) { throw new InvalidOperationException("Sub-types can only be adedd to non-sealed classes"); } MetaType derivedMeta = model[derivedType]; SubType subType = new SubType(fieldNumber, derivedMeta); ThrowIfFrozen(); derivedMeta.SetBaseType(this); // includes ThrowIfFrozen if (subTypes == null) subTypes = new BasicList(); subTypes.Add(subType); return this; }
static public int getItem(IntPtr l) { try { ProtoBuf.Meta.BasicList self = (ProtoBuf.Meta.BasicList)checkSelf(l); int v; checkType(l, 2, out v); var ret = self[v]; pushValue(l, true); pushValue(l, ret); return(2); } catch (Exception e) { return(error(l, e)); } }
static public int Add(IntPtr l) { try { ProtoBuf.Meta.BasicList self = (ProtoBuf.Meta.BasicList)checkSelf(l); System.Object a1; checkType(l, 2, out a1); var ret = self.Add(a1); pushValue(l, true); pushValue(l, ret); return(2); } catch (Exception e) { return(error(l, e)); } }
private static void TestEnumerableListPatterns(TypeModel model, BasicList candidates, Type iType) { if (iType.IsGenericType) { Type genericTypeDefinition = iType.GetGenericTypeDefinition(); if (!(genericTypeDefinition == model.MapType(typeof(IEnumerable <>))) && !(genericTypeDefinition == model.MapType(typeof(ICollection <>))) && !(genericTypeDefinition.FullName == "System.Collections.Concurrent.IProducerConsumerCollection`1")) { return; } Type[] genericArguments = iType.GetGenericArguments(); if (!candidates.Contains(genericArguments[0])) { candidates.Add(genericArguments[0]); } } }
/// <summary> /// Adds a known sub-type to the inheritance model /// </summary> public MetaType AddSubType(int fieldNumber, Type derivedType) { if (!type.IsClass || type.IsSealed) { throw new InvalidOperationException("Sub-types can only be adedd to non-sealed classes"); } MetaType derivedMeta = model[derivedType]; SubType subType = new SubType(fieldNumber, derivedMeta); ThrowIfFrozen(); derivedMeta.SetBaseType(this); // includes ThrowIfFrozen if (subTypes == null) { subTypes = new BasicList(); } subTypes.Add(subType); return(this); }
internal NodeEnumerator(BasicList.Node node) { this.position = -1; this.node = node; }
public override string GetSchema(Type type) { BasicList basicList = new BasicList(); MetaType metaType = null; bool flag = false; if (type == null) { BasicList.NodeEnumerator enumerator = types.GetEnumerator(); while (enumerator.MoveNext()) { MetaType surrogateOrBaseOrSelf = ((MetaType)enumerator.Current).GetSurrogateOrBaseOrSelf(deep: false); if (!basicList.Contains(surrogateOrBaseOrSelf)) { basicList.Add(surrogateOrBaseOrSelf); CascadeDependents(basicList, surrogateOrBaseOrSelf); } } } else { Type underlyingType = Helpers.GetUnderlyingType(type); if (underlyingType != null) { type = underlyingType; } flag = (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out WireType _, asReference: false, dynamicType: false, overwriteList: false, allowComplexTypes: false) != null); if (!flag) { int num = FindOrAddAuto(type, demand: false, addWithContractOnly: false, addEvenIfAutoDisabled: false); if (num < 0) { throw new ArgumentException("The type specified is not a contract-type", "type"); } metaType = ((MetaType)types[num]).GetSurrogateOrBaseOrSelf(deep: false); basicList.Add(metaType); CascadeDependents(basicList, metaType); } } StringBuilder stringBuilder = new StringBuilder(); string text = null; if (!flag) { foreach (MetaType item in (IEnumerable)((metaType == null) ? types : basicList)) { if (!item.IsList) { string @namespace = item.Type.Namespace; if (!Helpers.IsNullOrEmpty(@namespace) && [email protected]("System.")) { if (text == null) { text = @namespace; } else if (!(text == @namespace)) { text = null; break; } } } } } if (!Helpers.IsNullOrEmpty(text)) { stringBuilder.Append("package ").Append(text).Append(';'); Helpers.AppendLine(stringBuilder); } bool requiresBclImport = false; StringBuilder stringBuilder2 = new StringBuilder(); MetaType[] array = new MetaType[basicList.Count]; basicList.CopyTo(array, 0); Array.Sort(array, MetaType.Comparer.Default); if (flag) { Helpers.AppendLine(stringBuilder2).Append("message ").Append(type.Name) .Append(" {"); MetaType.NewLine(stringBuilder2, 1).Append("optional ").Append(GetSchemaTypeName(type, DataFormat.Default, asReference: false, dynamicType: false, ref requiresBclImport)) .Append(" value = 1;"); Helpers.AppendLine(stringBuilder2).Append('}'); } else { foreach (MetaType metaType3 in array) { if (!metaType3.IsList || metaType3 == metaType) { metaType3.WriteSchema(stringBuilder2, 0, ref requiresBclImport); } } } if (requiresBclImport) { stringBuilder.Append("import \"bcl.proto\"; // schema for protobuf-net's handling of core .NET types"); Helpers.AppendLine(stringBuilder); } return(Helpers.AppendLine(stringBuilder.Append(stringBuilder2)).ToString()); }
// Token: 0x0600036A RID: 874 RVA: 0x00012A1C File Offset: 0x00010C1C private void CascadeDependents(BasicList list, MetaType metaType) { if (metaType.IsList) { Type listItemType = TypeModel.GetListItemType(this, metaType.Type); WireType wireType; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, listItemType, out wireType, false, false, false, false) == null) { int num = this.FindOrAddAuto(listItemType, false, false, false); if (num >= 0) { MetaType metaType2 = ((MetaType)this.types[num]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); return; } } } } else { MetaType metaType2; if (metaType.IsAutoTuple) { MemberInfo[] array; if (MetaType.ResolveTupleConstructor(metaType.Type, out array) != null) { for (int i = 0; i < array.Length; i++) { Type type = null; if (array[i] is PropertyInfo) { type = ((PropertyInfo)array[i]).PropertyType; } else if (array[i] is FieldInfo) { type = ((FieldInfo)array[i]).FieldType; } WireType wireType2; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out wireType2, false, false, false, false) == null) { int num2 = this.FindOrAddAuto(type, false, false, false); if (num2 >= 0) { metaType2 = ((MetaType)this.types[num2]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } } } } else { foreach (object obj in metaType.Fields) { ValueMember valueMember = (ValueMember)obj; Type type2 = valueMember.ItemType; if (type2 == null) { type2 = valueMember.MemberType; } WireType wireType3; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type2, out wireType3, false, false, false, false) == null) { int num3 = this.FindOrAddAuto(type2, false, false, false); if (num3 >= 0) { metaType2 = ((MetaType)this.types[num3]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } } } if (metaType.HasSubtypes) { SubType[] subtypes = metaType.GetSubtypes(); for (int j = 0; j < subtypes.Length; j++) { metaType2 = subtypes[j].DerivedType.GetSurrogateOrSelf(); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } metaType2 = metaType.BaseType; if (metaType2 != null) { metaType2 = metaType2.GetSurrogateOrSelf(); } if (metaType2 != null && !list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } }
/// <summary> /// Fully compiles the current model into a static-compiled serialization dll /// (the serialization dll still requires protobuf-net for support services). /// </summary> /// <remarks>A full compilation is restricted to accessing public types / members</remarks> /// <param name="name">The name of the TypeModel class to create</param> /// <param name="path">The path for the new dll</param> /// <returns>An instance of the newly created compiled type-model</returns> public TypeModel Compile(string name, string path) { BuildAllSerializers(); Freeze(); bool save = !Helpers.IsNullOrEmpty(path); if (Helpers.IsNullOrEmpty(name)) { if (save) throw new ArgumentNullException("name"); name = Guid.NewGuid().ToString(); } AssemblyName an = new AssemblyName(); an.Name = name; AssemblyBuilder asm = AppDomain.CurrentDomain.DefineDynamicAssembly(an, (save ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run) ); ModuleBuilder module = save ? asm.DefineDynamicModule(name, path) : asm.DefineDynamicModule(name); Type baseType = typeof(TypeModel); TypeBuilder type = module.DefineType(name, (baseType.Attributes & ~TypeAttributes.Abstract) | TypeAttributes.Sealed, baseType); Compiler.CompilerContext ctx; int index = 0; bool hasInheritance = false; SerializerPair[] methodPairs = new SerializerPair[types.Count]; foreach (MetaType metaType in types) { MethodBuilder writeMethod = type.DefineMethod("Write" #if DEBUG + metaType.Type.Name #endif , MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard, typeof(void), new Type[] { metaType.Type, typeof(ProtoWriter) }); MethodBuilder readMethod = type.DefineMethod("Read" #if DEBUG + metaType.Type.Name #endif , MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard, metaType.Type, new Type[] { metaType.Type, typeof(ProtoReader) }); SerializerPair pair = new SerializerPair( GetKey(metaType.Type, true, false), GetKey(metaType.Type, true, true), metaType, writeMethod, readMethod, writeMethod.GetILGenerator(), readMethod.GetILGenerator()); methodPairs[index++] = pair; if (pair.MetaKey != pair.BaseKey) hasInheritance = true; } if (hasInheritance) { Array.Sort(methodPairs); } for(index = 0; index < methodPairs.Length ; index++) { SerializerPair pair = methodPairs[index]; ctx = new Compiler.CompilerContext(pair.SerializeBody, true, true, methodPairs); pair.Type.Serializer.EmitWrite(ctx, Compiler.Local.InputValue); ctx.Return(); ctx = new Compiler.CompilerContext(pair.DeserializeBody, true, false, methodPairs); pair.Type.Serializer.EmitRead(ctx, Compiler.Local.InputValue); if (!pair.Type.Serializer.ReturnsValue) { ctx.LoadValue(Compiler.Local.InputValue); } ctx.Return(); } FieldBuilder knownTypes = type.DefineField("knownTypes", typeof(Type[]), FieldAttributes.Private | FieldAttributes.InitOnly); ILGenerator il = Override(type, "GetKeyImpl"); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, knownTypes); il.Emit(OpCodes.Ldarg_1); // note that Array.IndexOf is not supported under CF il.EmitCall(OpCodes.Callvirt,typeof(IList).GetMethod( "IndexOf", new Type[] { typeof(object) }), null); if (hasInheritance) { il.DeclareLocal(typeof(int)); // loc-0 il.Emit(OpCodes.Dup); il.Emit(OpCodes.Stloc_0); BasicList getKeyLabels = new BasicList(); int lastKey = -1; for (int i = 0; i < methodPairs.Length; i++) { if (methodPairs[i].MetaKey == methodPairs[i].BaseKey) break; if (lastKey == methodPairs[i].BaseKey) { // add the last label again getKeyLabels.Add(getKeyLabels[getKeyLabels.Count - 1]); } else { // add a new unique label getKeyLabels.Add(il.DefineLabel()); lastKey = methodPairs[i].BaseKey; } } Label[] subtypeLabels = new Label[getKeyLabels.Count]; getKeyLabels.CopyTo(subtypeLabels, 0); il.Emit(OpCodes.Switch, subtypeLabels); il.Emit(OpCodes.Ldloc_0); // not a sub-type; use the original value il.Emit(OpCodes.Ret); lastKey = -1; // now output the different branches per sub-type (not derived type) for (int i = subtypeLabels.Length - 1; i >= 0; i--) { if (lastKey != methodPairs[i].BaseKey) { lastKey = methodPairs[i].BaseKey; // find the actual base-index for this base-key (i.e. the index of // the base-type) int keyIndex = -1; for (int j = subtypeLabels.Length; j < methodPairs.Length; j++) { if (methodPairs[j].BaseKey == lastKey && methodPairs[j].MetaKey == lastKey) { keyIndex = j; break; } } il.MarkLabel(subtypeLabels[i]); Compiler.CompilerContext.LoadValue(il, keyIndex); il.Emit(OpCodes.Ret); } } } else { il.Emit(OpCodes.Ret); } il = Override(type, "Serialize"); ctx = new Compiler.CompilerContext(il, false, true, methodPairs); // arg0 = this, arg1 = key, arg2=obj, arg3=dest Label[] jumpTable = new Label[types.Count]; for (int i = 0; i < jumpTable.Length; i++) { jumpTable[i] = il.DefineLabel(); } il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Switch, jumpTable); ctx.Return(); for (int i = 0; i < jumpTable.Length; i++) { SerializerPair pair = methodPairs[i]; il.MarkLabel(jumpTable[i]); il.Emit(OpCodes.Ldarg_2); ctx.CastFromObject(pair.Type.Type); il.Emit(OpCodes.Ldarg_3); il.EmitCall(OpCodes.Call, pair.Serialize, null); ctx.Return(); } il = Override(type, "Deserialize"); ctx = new Compiler.CompilerContext(il, false, false, methodPairs); // arg0 = this, arg1 = key, arg2=obj, arg3=source for (int i = 0; i < jumpTable.Length; i++) { jumpTable[i] = il.DefineLabel(); } il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Switch, jumpTable); ctx.LoadNullRef(); ctx.Return(); for (int i = 0; i < jumpTable.Length; i++) { SerializerPair pair = methodPairs[i]; il.MarkLabel(jumpTable[i]); Type keyType = pair.Type.Type; if (keyType.IsValueType) { il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.EmitCall(OpCodes.Call, EmitBoxedSerializer(type, i, keyType, methodPairs), null); ctx.Return(); } else { il.Emit(OpCodes.Ldarg_2); ctx.CastFromObject(keyType); il.Emit(OpCodes.Ldarg_3); il.EmitCall(OpCodes.Call, pair.Deserialize, null); ctx.Return(); } } ConstructorBuilder ctor = type.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Helpers.EmptyTypes); il = ctor.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, Helpers.GetConstructor(baseType, Helpers.EmptyTypes, true)); il.Emit(OpCodes.Ldarg_0); Compiler.CompilerContext.LoadValue(il, types.Count); il.Emit(OpCodes.Newarr, typeof(Type)); index = 0; foreach(SerializerPair pair in methodPairs) { il.Emit(OpCodes.Dup); Compiler.CompilerContext.LoadValue(il, index); il.Emit(OpCodes.Ldtoken, pair.Type.Type); il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); il.Emit(OpCodes.Stelem_Ref); index++; } il.Emit(OpCodes.Stfld, knownTypes); il.Emit(OpCodes.Ret); Type finalType = type.CreateType(); if(!Helpers.IsNullOrEmpty(path)) { asm.Save(path); Helpers.DebugWriteLine("Wrote dll:" + path); } return (TypeModel)Activator.CreateInstance(finalType); }
public override object Read(object value, ProtoReader source) { if (nested) { source.ReadFieldHeader(); } int field = source.FieldNumber; BasicList list = new BasicList(); if (packedWireType != WireType.None && source.WireType == WireType.String) { SubItemToken token = ProtoReader.StartSubItem(source); while (ProtoReader.HasSubValue(packedWireType, source)) { list.Add(Tail.Read(null, source)); } ProtoReader.EndSubItem(token, source); int oldLen = AppendToCollection ? ((value == null ? 0 : ((Array)value).Length)) : 0; Array result = Array.CreateInstance(itemType, oldLen + list.Count); if (oldLen != 0) ((Array)value).CopyTo(result, 0); list.CopyTo(result, oldLen); return result; } else { bool readObject = true; int arrayKey = 0; value = value ?? Array.CreateInstance(itemType, 0); if (AsReference) { int objectKey = source.ReadInt32(); if (objectKey > 0) { value = source.NetCache.GetKeyedObject(objectKey); readObject = false; } else { bool dummy; arrayKey = source.NetCache.AddObjectKey(value, out dummy); } } else { bool isEmpty = source.ReadInt32() == 1; if (isEmpty) { return value; } } if (readObject) { while (source.TryReadFieldHeader(field)) { list.Add(Tail.Read(null, source)); } Array newArray = Array.CreateInstance(itemType, list.Count); list.CopyTo(newArray, 0); if (AsReference) { source.NetCache.UpdateKeyedObject(arrayKey, value, newArray); } value = newArray; } } return value; }
private static ProtoMemberAttribute NormalizeProtoMember(MemberInfo member, AttributeFamily family, bool forced, bool isEnum, BasicList partialMembers, int dataMemberOffset, bool inferByTagName) { if (member == null || (family == AttributeFamily.None && !isEnum)) { return(null); // nix } int fieldNumber = int.MinValue, minAcceptFieldNumber = inferByTagName ? -1 : 1; string name = null; bool isPacked = false, ignore = false, done = false, isRequired = false, asReference = false, dynamicType = false, tagIsPinned = false, overwriteList = false; DataFormat dataFormat = DataFormat.Default; if (isEnum) { forced = true; } object[] attribs = member.GetCustomAttributes(true); Attribute attrib; if (isEnum) { attrib = GetAttribute(attribs, "ProtoBuf.ProtoIgnoreAttribute"); if (attrib != null) { ignore = true; } else { attrib = GetAttribute(attribs, "ProtoBuf.ProtoEnumAttribute"); fieldNumber = Convert.ToInt32(((FieldInfo)member).GetValue(null)); if (attrib != null) { GetFieldName(ref name, attrib, "Name"); if ((bool)attrib.GetType().GetMethod("HasValue").Invoke(attrib, null)) { fieldNumber = (int)GetMemberValue(attrib, "Value"); } } } done = true; } if (!ignore && !done) // always consider ProtoMember { attrib = GetAttribute(attribs, "ProtoBuf.ProtoMemberAttribute"); GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.ProtoIgnoreAttribute"); if (!ignore && attrib != null) { GetFieldNumber(ref fieldNumber, attrib, "Tag"); GetFieldName(ref name, attrib, "Name"); GetFieldBoolean(ref isRequired, attrib, "IsRequired"); GetFieldBoolean(ref isPacked, attrib, "IsPacked"); GetFieldBoolean(ref overwriteList, attrib, "OverwriteList"); GetDataFormat(ref dataFormat, attrib, "DataFormat"); GetFieldBoolean(ref asReference, attrib, "AsReference"); GetFieldBoolean(ref dynamicType, attrib, "DynamicType"); done = tagIsPinned = fieldNumber > 0; // note minAcceptFieldNumber only applies to non-proto } if (!done && partialMembers != null) { foreach (ProtoPartialMemberAttribute ppma in partialMembers) { if (ppma.MemberName == member.Name) { GetFieldNumber(ref fieldNumber, ppma, "Tag"); GetFieldName(ref name, ppma, "Name"); GetFieldBoolean(ref isRequired, ppma, "IsRequired"); GetFieldBoolean(ref isPacked, ppma, "IsPacked"); GetFieldBoolean(ref overwriteList, attrib, "OverwriteList"); GetDataFormat(ref dataFormat, ppma, "DataFormat"); GetFieldBoolean(ref asReference, ppma, "AsReference"); GetFieldBoolean(ref dynamicType, ppma, "DynamicType"); if (done = tagIsPinned = fieldNumber > 0) { break; // note minAcceptFieldNumber only applies to non-proto } } } } } if (!ignore && !done && HasFamily(family, AttributeFamily.DataContractSerialier)) { attrib = GetAttribute(attribs, "System.Runtime.Serialization.DataMemberAttribute"); if (attrib != null) { GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "Name"); GetFieldBoolean(ref isRequired, attrib, "IsRequired"); done = fieldNumber >= minAcceptFieldNumber; if (done) { fieldNumber += dataMemberOffset; // dataMemberOffset only applies to DCS flags, to allow us to "bump" WCF by a notch } } } if (!ignore && !done && HasFamily(family, AttributeFamily.XmlSerializer)) { attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlElementAttribute"); if (attrib == null) { attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlArrayAttribute"); } GetIgnore(ref ignore, attrib, attribs, "System.Xml.Serialization.XmlIgnoreAttribute"); if (attrib != null && !ignore) { GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "ElementName"); done = fieldNumber >= minAcceptFieldNumber; } } if (!ignore && !done) { if (GetAttribute(attribs, "System.NonSerializedAttribute") != null) { ignore = true; } } if (ignore || (fieldNumber < minAcceptFieldNumber && !forced)) { return(null); } ProtoMemberAttribute result = new ProtoMemberAttribute(fieldNumber, forced || inferByTagName); result.AsReference = asReference; result.DataFormat = dataFormat; result.DynamicType = dynamicType; result.IsPacked = isPacked; result.OverwriteList = overwriteList; result.IsRequired = isRequired; result.Name = Helpers.IsNullOrEmpty(name) ? member.Name : name; result.Member = member; result.TagIsPinned = tagIsPinned; return(result); }
bool InternalsVisible(Assembly assembly) { #if PHONE8 || SILVERLIGHT || FX11 return false; #else if (Helpers.IsNullOrEmpty(assemblyName)) return false; if (knownTrustedAssemblies != null) { if (knownTrustedAssemblies.IndexOfReference(assembly) >= 0) { return true; } } if (knownUntrustedAssemblies != null) { if (knownUntrustedAssemblies.IndexOfReference(assembly) >= 0) { return false; } } bool isTrusted = false; Type attributeType = MapType(typeof(System.Runtime.CompilerServices.InternalsVisibleToAttribute)); if(attributeType == null) return false; #if FEAT_IKVM foreach (CustomAttributeData attrib in assembly.__GetCustomAttributes(attributeType, false)) { if (attrib.ConstructorArguments.Count == 1) { string privelegedAssembly = attrib.ConstructorArguments[0].Value as string; if (privelegedAssembly == assemblyName) { isTrusted = true; break; } } } #else foreach(System.Runtime.CompilerServices.InternalsVisibleToAttribute attrib in assembly.GetCustomAttributes(attributeType, false)) { if (attrib.AssemblyName == assemblyName) { isTrusted = true; break; } } #endif if (isTrusted) { if (knownTrustedAssemblies == null) knownTrustedAssemblies = new BasicList(); knownTrustedAssemblies.Add(assembly); } else { if (knownUntrustedAssemblies == null) knownUntrustedAssemblies = new BasicList(); knownUntrustedAssemblies.Add(assembly); } return isTrusted; #endif }
// Token: 0x060032F1 RID: 13041 RVA: 0x001283C5 File Offset: 0x001267C5 public Group(int first) { First = first; Items = new BasicList(); }
void ReadSInstance(ProtoReader reader, SInstance sInstance, CLS_Environment environment) { List<CLS_Content.Value> values; List<string> keywords; GetSortMembers(sInstance, out values, out keywords); int fieldNumber = 0; while ((fieldNumber = reader.ReadFieldHeader()) > 0) { Type memberT = values[fieldNumber - 1].type; CLS_Content.Value memberV = values[fieldNumber - 1]; string sClassName = keywords[fieldNumber - 1]; if (memberT == null) { memberT = typeof(SInstance); sClassName = ((SType)memberV.type).Name; } Type itemType = GetItemType(memberT); if (itemType != null) { sClassName = sInstance.type.members[sClassName].type.keyword; // 数组判断 if (memberT.IsArray) { string itemClass = sClassName.Substring(0, sClassName.Length - 2); // 从 xxx[] 中提取xxx BasicList list = new BasicList(); do { list.Add(ReadField(reader, itemType, itemClass, environment)); } while (reader.TryReadFieldHeader(fieldNumber)); Array result = Array.CreateInstance(itemType, list.Count); list.CopyTo(result, 0); memberV.value = result; } // 列表判断 else { string itemClass = sClassName.Substring(5, sClassName.Length - 6); // 从 List<xxx> 中提取xxx ICLS_Type iType = environment.GetTypeByKeywordQuiet(sClassName); CLS_Content content = CLS_Content.NewContent(environment); memberV.value = iType.function.New(content, m_emptyParams).value; CLS_Content.PoolContent(content); IList list = (IList)memberV.value; do { list.Add(ReadField(reader, itemType, itemClass, environment)); } while (reader.TryReadFieldHeader(fieldNumber)); } } else { memberV.value = ReadField(reader, memberT, sClassName, environment); } } }
private static ProtoMemberAttribute NormalizeProtoMember(MemberInfo member, AttributeFamily family, bool forced, bool isEnum, BasicList partialMembers, int dataMemberOffset, bool inferByTagName) { if (member == null || (family == AttributeFamily.None && !isEnum)) return null; // nix int fieldNumber = int.MinValue, minAcceptFieldNumber = inferByTagName ? -1 : 1; string name = null; bool isPacked = false, ignore = false, done = false, isRequired = false, asReference = false, dynamicType = false, tagIsPinned = false, overwriteList = false; DataFormat dataFormat = DataFormat.Default; if (isEnum) forced = true; object[] attribs = member.GetCustomAttributes(true); Attribute attrib; if (isEnum) { attrib = GetAttribute(attribs, "ProtoBuf.ProtoIgnoreAttribute"); if (attrib != null) { ignore = true; } else { attrib = GetAttribute(attribs, "ProtoBuf.ProtoEnumAttribute"); fieldNumber = Convert.ToInt32(((FieldInfo)member).GetValue(null)); if (attrib != null) { GetFieldName(ref name, attrib, "Name"); if ((bool)attrib.GetType().GetMethod("HasValue").Invoke(attrib, null)) { fieldNumber = (int)GetMemberValue(attrib, "Value"); } } } done = true; } if (!ignore && !done) // always consider ProtoMember { attrib = GetAttribute(attribs, "ProtoBuf.ProtoMemberAttribute"); GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.ProtoIgnoreAttribute"); if (!ignore && attrib != null) { GetFieldNumber(ref fieldNumber, attrib, "Tag"); GetFieldName(ref name, attrib, "Name"); GetFieldBoolean(ref isRequired, attrib, "IsRequired"); GetFieldBoolean(ref isPacked, attrib, "IsPacked"); GetFieldBoolean(ref overwriteList, attrib, "OverwriteList"); GetDataFormat(ref dataFormat, attrib, "DataFormat"); GetFieldBoolean(ref asReference, attrib, "AsReference"); GetFieldBoolean(ref dynamicType, attrib, "DynamicType"); done = tagIsPinned = fieldNumber > 0; // note minAcceptFieldNumber only applies to non-proto } if (!done && partialMembers != null) { foreach (ProtoPartialMemberAttribute ppma in partialMembers) { if (ppma.MemberName == member.Name) { GetFieldNumber(ref fieldNumber, ppma, "Tag"); GetFieldName(ref name, ppma, "Name"); GetFieldBoolean(ref isRequired, ppma, "IsRequired"); GetFieldBoolean(ref isPacked, ppma, "IsPacked"); GetFieldBoolean(ref overwriteList, attrib, "OverwriteList"); GetDataFormat(ref dataFormat, ppma, "DataFormat"); GetFieldBoolean(ref asReference, ppma, "AsReference"); GetFieldBoolean(ref dynamicType, ppma, "DynamicType"); if (done = tagIsPinned = fieldNumber > 0) break; // note minAcceptFieldNumber only applies to non-proto } } } } if (!ignore && !done && HasFamily(family, AttributeFamily.DataContractSerialier)) { attrib = GetAttribute(attribs, "System.Runtime.Serialization.DataMemberAttribute"); if (attrib != null) { GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "Name"); GetFieldBoolean(ref isRequired, attrib, "IsRequired"); done = fieldNumber >= minAcceptFieldNumber; if (done) fieldNumber += dataMemberOffset; // dataMemberOffset only applies to DCS flags, to allow us to "bump" WCF by a notch } } if (!ignore && !done && HasFamily(family, AttributeFamily.XmlSerializer)) { attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlElementAttribute"); if(attrib == null) attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlArrayAttribute"); GetIgnore(ref ignore, attrib, attribs, "System.Xml.Serialization.XmlIgnoreAttribute"); if (attrib != null && !ignore) { GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "ElementName"); done = fieldNumber >= minAcceptFieldNumber; } } if (!ignore && !done) { if (GetAttribute(attribs, "System.NonSerializedAttribute") != null) ignore = true; } if (ignore || (fieldNumber < minAcceptFieldNumber && !forced)) return null; ProtoMemberAttribute result = new ProtoMemberAttribute(fieldNumber, forced || inferByTagName); result.AsReference = asReference; result.DataFormat = dataFormat; result.DynamicType = dynamicType; result.IsPacked = isPacked; result.OverwriteList = overwriteList; result.IsRequired = isRequired; result.Name = Helpers.IsNullOrEmpty(name) ? member.Name : name; result.Member = member; result.TagIsPinned = tagIsPinned; return result; }
internal void ApplyDefaultBehaviour() { if (type.BaseType != null && model.FindWithoutAdd(type.BaseType) == null && GetContractFamily(type.BaseType, null) != MetaType.AttributeFamily.None) { model.FindOrAddAuto(type.BaseType, true, false, false); } object[] typeAttribs = type.GetCustomAttributes(true); AttributeFamily family = GetContractFamily(type, typeAttribs); bool isEnum = type.IsEnum; if(family == AttributeFamily.None && !isEnum) return; // and you'd like me to do what, exactly? BasicList partialIgnores = null, partialMembers = null; int dataMemberOffset = 0, implicitFirstTag = 1; bool inferTagByName = model.InferTagFromNameDefault; ImplicitFields implicitMode = ImplicitFields.None; for (int i = 0; i < typeAttribs.Length; i++) { Attribute item = (Attribute)typeAttribs[i]; if (!isEnum && item is ProtoIncludeAttribute) { ProtoIncludeAttribute pia = (ProtoIncludeAttribute)item; Type knownType = pia.ResolveKnownType(type.Assembly); if (knownType == null) { throw new InvalidOperationException("Unable to resolve sub-type: " + pia.KnownTypeName); } AddSubType(pia.Tag, knownType); } if(item is ProtoPartialIgnoreAttribute) { if(partialIgnores == null) partialIgnores = new BasicList(); partialIgnores.Add(((ProtoPartialIgnoreAttribute)item).MemberName); } if (!isEnum && item is ProtoPartialMemberAttribute) { if (partialMembers == null) partialMembers = new BasicList(); partialMembers.Add(item); } if (!isEnum && item is ProtoContractAttribute) { ProtoContractAttribute pca = (ProtoContractAttribute)item; dataMemberOffset = pca.DataMemberOffset; if (pca.InferTagFromNameHasValue) inferTagByName = pca.InferTagFromName; implicitMode = pca.ImplicitFields; UseConstructor = !pca.SkipConstructor; if(pca.ImplicitFirstTag > 0) implicitFirstTag = pca.ImplicitFirstTag; } } if (implicitMode != ImplicitFields.None) { family &= AttributeFamily.ProtoBuf; // with implicit fields, **only** proto attributes are important } MethodInfo[] callbacks = null; BasicList members = new BasicList(); foreach (MemberInfo member in type.GetMembers(isEnum ? BindingFlags.Public | BindingFlags.Static : BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (member.DeclaringType != type) continue; if (member.IsDefined(typeof(ProtoIgnoreAttribute), true)) continue; if (partialIgnores != null && partialIgnores.Contains(member.Name)) continue; bool forced = false, isPublic, isField; Type effectiveType; switch (member.MemberType) { case MemberTypes.Property: PropertyInfo property = (PropertyInfo)member; effectiveType = property.PropertyType; isPublic = property.GetGetMethod(false) != null; isField = false; goto ProcessMember; case MemberTypes.Field: FieldInfo field = (FieldInfo)member; effectiveType = field.FieldType; isPublic = field.IsPublic; isField = true; ProcessMember: switch(implicitMode) { case ImplicitFields.AllFields: if (isField) forced = true; break; case ImplicitFields.AllPublic: if (isPublic) forced = true; break; } if (effectiveType.IsSubclassOf(typeof(Delegate))) continue; // we just don't like delegate types ;p ProtoMemberAttribute normalizedAttribute = NormalizeProtoMember(member, family, forced, isEnum, partialMembers, dataMemberOffset, inferTagByName); if(normalizedAttribute != null) members.Add(normalizedAttribute); break; case MemberTypes.Method: if (isEnum) continue; MethodInfo method = (MethodInfo)member; object[] memberAttribs = Attribute.GetCustomAttributes(method); if (memberAttribs != null && memberAttribs.Length > 0) { CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeSerializationAttribute", ref callbacks, 0); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterSerializationAttribute", ref callbacks, 1); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeDeserializationAttribute", ref callbacks, 2); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterDeserializationAttribute", ref callbacks, 3); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializingAttribute", ref callbacks, 4); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializedAttribute", ref callbacks, 5); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializingAttribute", ref callbacks, 6); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializedAttribute", ref callbacks, 7); } break; } } ProtoMemberAttribute[] arr = new ProtoMemberAttribute[members.Count]; members.CopyTo(arr, 0); if (inferTagByName || implicitMode != ImplicitFields.None) { Array.Sort(arr); int nextTag = implicitFirstTag; foreach (ProtoMemberAttribute normalizedAttribute in arr) { if (!normalizedAttribute.TagIsPinned) // if ProtoMember etc sets a tag, we'll trust it { normalizedAttribute.Rebase(nextTag++); } } } foreach (ProtoMemberAttribute normalizedAttribute in arr) { ValueMember vm = ApplyDefaultBehaviour(isEnum, normalizedAttribute); if (vm != null) { Add(vm); } } if (callbacks != null) { SetCallbacks(Coalesce(callbacks, 0, 4), Coalesce(callbacks, 1, 5), Coalesce(callbacks, 2, 6), Coalesce(callbacks, 3, 7)); } }
private IProtoTypeSerializer BuildSerializer() { if (type.IsEnum) { //return new TagDecorator(ProtoBuf.Serializer.ListItemTag, WireType.Variant, false, new EnumSerializer(type, GetEnumMap())); return new TypeSerializer(type, new int[] { ProtoBuf.Serializer.ListItemTag }, new IProtoSerializer[] { new TagDecorator(ProtoBuf.Serializer.ListItemTag, WireType.Variant, false, new EnumSerializer(type, GetEnumMap())) }, null, true, true, null, constructType); } if (surrogate != null) { MetaType mt = model[surrogate], mtBase; while ((mtBase = mt.baseType) != null) { mt = mtBase; } return new SurrogateSerializer(type, surrogate, mt.Serializer); } Type itemType = TypeModel.GetListItemType(type); if (itemType != null) { ValueMember fakeMember = new ValueMember(model, ProtoBuf.Serializer.ListItemTag, type, itemType, type, DataFormat.Default); return new TypeSerializer(type, new int[] { ProtoBuf.Serializer.ListItemTag }, new IProtoSerializer[] { fakeMember.Serializer }, null, true, true, null, constructType); } fields.Trim(); int fieldCount = fields.Count; int subTypeCount = subTypes == null ? 0 : subTypes.Count; int[] fieldNumbers = new int[fieldCount + subTypeCount]; IProtoSerializer[] serializers = new IProtoSerializer[fieldCount + subTypeCount]; int i = 0; if (subTypeCount != 0) { foreach (SubType subType in subTypes) { fieldNumbers[i] = subType.FieldNumber; serializers[i++] = subType.Serializer; } } if (fieldCount != 0) { foreach (ValueMember member in fields) { fieldNumbers[i] = member.FieldNumber; serializers[i++] = member.Serializer; } } BasicList baseCtorCallbacks = null; MetaType tmp = BaseType; while (tmp != null) { MethodInfo method = tmp.HasCallbacks ? tmp.Callbacks.BeforeDeserialize : null; if (method != null) { if (baseCtorCallbacks == null) baseCtorCallbacks = new BasicList(); baseCtorCallbacks.Add(method); } tmp = tmp.BaseType; } MethodInfo[] arr = null; if (baseCtorCallbacks != null) { arr = new MethodInfo[baseCtorCallbacks.Count]; baseCtorCallbacks.CopyTo(arr, 0); Array.Reverse(arr); } return new TypeSerializer(type, fieldNumbers, serializers, arr, baseType == null, UseConstructor, callbacks, constructType); }
private bool TryDeserializeList(TypeModel model, ProtoReader reader, DataFormat format, int tag, Type listType, Type itemType, ref object value) { bool isList; MethodInfo methodInfo = ResolveListAdd(model, listType, itemType, out isList); if (methodInfo == null) { throw new NotSupportedException("Unknown list variant: " + listType.FullName); } bool result = false; object value2 = null; IList list = value as IList; object[] array = isList ? null : new object[1]; BasicList basicList = listType.IsArray ? new BasicList() : null; while (TryDeserializeAuxiliaryType(reader, format, tag, itemType, ref value2, skipOtherFields: true, asListItem: true, autoCreate: true, insideList: true)) { result = true; if (value == null && basicList == null) { value = CreateListInstance(listType, itemType); list = (value as IList); } if (list != null) { list.Add(value2); } else if (basicList != null) { basicList.Add(value2); } else { array[0] = value2; methodInfo.Invoke(value, array); } value2 = null; } if (basicList != null) { if (value != null) { if (basicList.Count != 0) { Array array2 = (Array)value; Array array3 = Array.CreateInstance(itemType, array2.Length + basicList.Count); Array.Copy(array2, array3, array2.Length); basicList.CopyTo(array3, array2.Length); value = array3; } } else { Array array3 = Array.CreateInstance(itemType, basicList.Count); basicList.CopyTo(array3, 0); value = array3; } } return(result); }
internal static Type GetListItemType(TypeModel model, Type listType) { if (listType == model.MapType(typeof(string)) || listType.IsArray || !model.MapType(typeof(IEnumerable)).IsAssignableFrom(listType)) { return(null); } BasicList basicList = new BasicList(); MethodInfo[] methods = listType.GetMethods(); foreach (MethodInfo methodInfo in methods) { if (!methodInfo.IsStatic && !(methodInfo.Name != "Add")) { ParameterInfo[] parameters = methodInfo.GetParameters(); Type parameterType; if (parameters.Length == 1 && !basicList.Contains(parameterType = parameters[0].ParameterType)) { basicList.Add(parameterType); } } } string name = listType.Name; if (name == null || (name.IndexOf("Queue") < 0 && name.IndexOf("Stack") < 0)) { TestEnumerableListPatterns(model, basicList, listType); Type[] interfaces = listType.GetInterfaces(); foreach (Type iType in interfaces) { TestEnumerableListPatterns(model, basicList, iType); } } PropertyInfo[] properties = listType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (!(propertyInfo.Name != "Item") && !basicList.Contains(propertyInfo.PropertyType)) { ParameterInfo[] indexParameters = propertyInfo.GetIndexParameters(); if (indexParameters.Length == 1 && indexParameters[0].ParameterType == model.MapType(typeof(int))) { basicList.Add(propertyInfo.PropertyType); } } } switch (basicList.Count) { case 0: return(null); case 1: return((Type)basicList[0]); case 2: if (CheckDictionaryAccessors(model, (Type)basicList[0], (Type)basicList[1])) { return((Type)basicList[0]); } if (CheckDictionaryAccessors(model, (Type)basicList[1], (Type)basicList[0])) { return((Type)basicList[1]); } break; } return(null); }
private void WriteGetKeyImpl(TypeBuilder type, bool hasInheritance, SerializerPair[] methodPairs, Compiler.CompilerContext.ILVersion ilVersion, string assemblyName, out ILGenerator il, out int knownTypesCategory, out FieldBuilder knownTypes, out Type knownTypesLookupType) { il = Override(type, "GetKeyImpl"); Compiler.CompilerContext ctx = new Compiler.CompilerContext(il, false, false, methodPairs, this, ilVersion, assemblyName, MapType(typeof(System.Type), true)); if (types.Count <= KnownTypes_ArrayCutoff) { knownTypesCategory = KnownTypes_Array; knownTypesLookupType = MapType(typeof(System.Type[]), true); } else { #if NO_GENERICS knownTypesLookupType = null; #else knownTypesLookupType = MapType(typeof(System.Collections.Generic.Dictionary<System.Type, int>), false); #endif if (knownTypesLookupType == null) { knownTypesLookupType = MapType(typeof(Hashtable), true); knownTypesCategory = KnownTypes_Hashtable; } else { knownTypesCategory = KnownTypes_Dictionary; } } knownTypes = type.DefineField("knownTypes", knownTypesLookupType, FieldAttributes.Private | FieldAttributes.InitOnly | FieldAttributes.Static); switch (knownTypesCategory) { case KnownTypes_Array: { il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldarg_1); // note that Array.IndexOf is not supported under CF il.EmitCall(OpCodes.Callvirt, MapType(typeof(IList)).GetMethod( "IndexOf", new Type[] { MapType(typeof(object)) }), null); if (hasInheritance) { il.DeclareLocal(MapType(typeof(int))); // loc-0 il.Emit(OpCodes.Dup); il.Emit(OpCodes.Stloc_0); BasicList getKeyLabels = new BasicList(); int lastKey = -1; for (int i = 0; i < methodPairs.Length; i++) { if (methodPairs[i].MetaKey == methodPairs[i].BaseKey) break; if (lastKey == methodPairs[i].BaseKey) { // add the last label again getKeyLabels.Add(getKeyLabels[getKeyLabels.Count - 1]); } else { // add a new unique label getKeyLabels.Add(ctx.DefineLabel()); lastKey = methodPairs[i].BaseKey; } } Compiler.CodeLabel[] subtypeLabels = new Compiler.CodeLabel[getKeyLabels.Count]; getKeyLabels.CopyTo(subtypeLabels, 0); ctx.Switch(subtypeLabels); il.Emit(OpCodes.Ldloc_0); // not a sub-type; use the original value il.Emit(OpCodes.Ret); lastKey = -1; // now output the different branches per sub-type (not derived type) for (int i = subtypeLabels.Length - 1; i >= 0; i--) { if (lastKey != methodPairs[i].BaseKey) { lastKey = methodPairs[i].BaseKey; // find the actual base-index for this base-key (i.e. the index of // the base-type) int keyIndex = -1; for (int j = subtypeLabels.Length; j < methodPairs.Length; j++) { if (methodPairs[j].BaseKey == lastKey && methodPairs[j].MetaKey == lastKey) { keyIndex = j; break; } } ctx.MarkLabel(subtypeLabels[i]); Compiler.CompilerContext.LoadValue(il, keyIndex); il.Emit(OpCodes.Ret); } } } else { il.Emit(OpCodes.Ret); } } break; case KnownTypes_Dictionary: { LocalBuilder result = il.DeclareLocal(MapType(typeof(int))); Label otherwise = il.DefineLabel(); il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloca_S, result); il.EmitCall(OpCodes.Callvirt, knownTypesLookupType.GetMethod("TryGetValue", BindingFlags.Instance | BindingFlags.Public), null); il.Emit(OpCodes.Brfalse_S, otherwise); il.Emit(OpCodes.Ldloc_S, result); il.Emit(OpCodes.Ret); il.MarkLabel(otherwise); il.Emit(OpCodes.Ldc_I4_M1); il.Emit(OpCodes.Ret); } break; case KnownTypes_Hashtable: { Label otherwise = il.DefineLabel(); il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldarg_1); il.EmitCall(OpCodes.Callvirt, knownTypesLookupType.GetProperty("Item").GetGetMethod(), null); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Brfalse_S, otherwise); #if FX11 il.Emit(OpCodes.Unbox, MapType(typeof(int))); il.Emit(OpCodes.Ldobj, MapType(typeof(int))); #else if (ilVersion == Compiler.CompilerContext.ILVersion.Net1) { il.Emit(OpCodes.Unbox, MapType(typeof(int))); il.Emit(OpCodes.Ldobj, MapType(typeof(int))); } else { il.Emit(OpCodes.Unbox_Any, MapType(typeof(int))); } #endif il.Emit(OpCodes.Ret); il.MarkLabel(otherwise); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldc_I4_M1); il.Emit(OpCodes.Ret); } break; default: throw new InvalidOperationException(); } }
private void WriteAssemblyAttributes(CompilerOptions options, string assemblyName, AssemblyBuilder asm) { if (!Helpers.IsNullOrEmpty(options.TargetFrameworkName)) { // get [TargetFramework] from mscorlib/equivalent and burn into the new assembly Type versionAttribType = null; try { // this is best-endeavours only versionAttribType = GetType("System.Runtime.Versioning.TargetFrameworkAttribute", MapType(typeof(string)).Assembly); } catch { /* don't stress */ } if (versionAttribType != null) { PropertyInfo[] props; object[] propValues; if (Helpers.IsNullOrEmpty(options.TargetFrameworkDisplayName)) { props = new PropertyInfo[0]; propValues = new object[0]; } else { props = new PropertyInfo[1] { versionAttribType.GetProperty("FrameworkDisplayName") }; propValues = new object[1] { options.TargetFrameworkDisplayName }; } CustomAttributeBuilder builder = new CustomAttributeBuilder( versionAttribType.GetConstructor(new Type[] { MapType(typeof(string)) }), new object[] { options.TargetFrameworkName }, props, propValues); asm.SetCustomAttribute(builder); } } // copy assembly:InternalsVisibleTo Type internalsVisibleToAttribType = null; #if !FX11 try { internalsVisibleToAttribType = MapType(typeof(System.Runtime.CompilerServices.InternalsVisibleToAttribute)); } catch { /* best endeavors only */ } #endif if (internalsVisibleToAttribType != null) { BasicList internalAssemblies = new BasicList(), consideredAssemblies = new BasicList(); foreach (MetaType metaType in types) { Assembly assembly = metaType.Type.Assembly; if (consideredAssemblies.IndexOfReference(assembly) >= 0) continue; consideredAssemblies.Add(assembly); AttributeMap[] assemblyAttribsMap = AttributeMap.Create(this, assembly); for (int i = 0; i < assemblyAttribsMap.Length; i++) { if (assemblyAttribsMap[i].AttributeType != internalsVisibleToAttribType) continue; object privelegedAssemblyObj; assemblyAttribsMap[i].TryGet("AssemblyName", out privelegedAssemblyObj); string privelegedAssemblyName = privelegedAssemblyObj as string; if (privelegedAssemblyName == assemblyName || Helpers.IsNullOrEmpty(privelegedAssemblyName)) continue; // ignore if (internalAssemblies.IndexOfString(privelegedAssemblyName) >= 0) continue; // seen it before internalAssemblies.Add(privelegedAssemblyName); CustomAttributeBuilder builder = new CustomAttributeBuilder( internalsVisibleToAttribType.GetConstructor(new Type[] { MapType(typeof(string)) }), new object[] { privelegedAssemblyName }); asm.SetCustomAttribute(builder); } } } }
private IProtoTypeSerializer BuildSerializer() { if (surrogate != null) return new SurrogateSerializer(type, model[surrogate].Serializer); fields.Trim(); int fieldCount = fields.Count; int subTypeCount = subTypes == null ? 0 : subTypes.Count; int[] fieldNumbers = new int[fieldCount + subTypeCount]; IProtoSerializer[] serializers = new IProtoSerializer[fieldCount + subTypeCount]; int i = 0; if (subTypeCount != 0) { foreach (SubType subType in subTypes) { fieldNumbers[i] = subType.FieldNumber; serializers[i++] = subType.Serializer; } } if (fieldCount != 0) { foreach (ValueMember member in fields) { fieldNumbers[i] = member.FieldNumber; serializers[i++] = member.Serializer; } } BasicList baseCtorCallbacks = null; MetaType tmp = BaseType; while (tmp != null) { MethodInfo method = tmp.HasCallbacks ? tmp.Callbacks.BeforeDeserialize : null; if (method != null) { if (baseCtorCallbacks == null) baseCtorCallbacks = new BasicList(); baseCtorCallbacks.Add(method); } tmp = tmp.BaseType; } MethodInfo[] arr = null; if (baseCtorCallbacks != null) { arr = new MethodInfo[baseCtorCallbacks.Count]; baseCtorCallbacks.CopyTo(arr, 0); Array.Reverse(arr); } return new TypeSerializer(type, fieldNumbers, serializers, arr, baseType == null, useConstructor, callbacks); }
internal static BasicList GetContiguousGroups(int[] keys, object[] values) { if (keys == null) throw new ArgumentNullException("keys"); if (values == null) throw new ArgumentNullException("values"); if (values.Length < keys.Length) throw new ArgumentException("Not all keys are covered by values", "values"); BasicList outer = new BasicList(); Group group = null; for (int i = 0; i < keys.Length; i++) { if (i == 0 || keys[i] != keys[i - 1]) { group = null; } if (group == null) { group = new Group(keys[i]); outer.Add(group); } group.Items.Add(values[i]); } return outer; }
internal void ApplyDefaultBehaviour() { if (model.FindWithoutAdd(type.BaseType) == null && GetContractFamily(type.BaseType, null) != MetaType.AttributeFamily.None) { model.FindOrAddAuto(type.BaseType, true, false, false); } object[] typeAttribs = type.GetCustomAttributes(true); AttributeFamily family = GetContractFamily(type, typeAttribs); bool isEnum = type.IsEnum; if(family == AttributeFamily.None && !isEnum) return; // and you'd like me to do what, exactly? BasicList partialIgnores = null, partialMembers = null; for (int i = 0; i < typeAttribs.Length; i++) { if (!isEnum && typeAttribs[i] is ProtoIncludeAttribute) { ProtoIncludeAttribute pia = (ProtoIncludeAttribute)typeAttribs[i]; AddSubType(pia.Tag, pia.KnownType); } if(typeAttribs[i] is ProtoPartialIgnoreAttribute) { if(partialIgnores == null) partialIgnores = new BasicList(); partialIgnores.Add(((ProtoPartialIgnoreAttribute)typeAttribs[i]).MemberName); } if (!isEnum && typeAttribs[i] is ProtoPartialMemberAttribute) { if (partialMembers == null) partialMembers = new BasicList(); partialMembers.Add(typeAttribs[i]); } } MethodInfo[] callbacks = null; foreach (MemberInfo member in type.GetMembers(isEnum ? BindingFlags.Public | BindingFlags.Static : BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (member.DeclaringType != type) continue; if (member.IsDefined(typeof(ProtoIgnoreAttribute), true)) continue; if (partialIgnores != null && partialIgnores.Contains(member.Name)) continue; switch (member.MemberType) { case MemberTypes.Property: case MemberTypes.Field: ValueMember vm = ApplyDefaultBehaviour(isEnum, family, member, partialMembers); if (vm != null) { Add(vm); } break; case MemberTypes.Method: if (isEnum) continue; MethodInfo method = (MethodInfo)member; object[] memberAttribs = Attribute.GetCustomAttributes(method); if (memberAttribs != null && memberAttribs.Length > 0) { CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeSerializationAttribute", ref callbacks, 0); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterSerializationAttribute", ref callbacks, 1); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeDeserializationAttribute", ref callbacks, 2); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterDeserializationAttribute", ref callbacks, 3); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializingAttribute", ref callbacks, 4); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializedAttribute", ref callbacks, 5); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializingAttribute", ref callbacks, 6); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializedAttribute", ref callbacks, 7); } break; } } if (callbacks != null) { SetCallbacks(callbacks[0] ?? callbacks[4], callbacks[1] ?? callbacks[5], callbacks[2] ?? callbacks[6], callbacks[3] ?? callbacks[7]); } }
private void CascadeDependents(BasicList list, MetaType metaType) { if (metaType.IsList) { Type listItemType = TypeModel.GetListItemType(this, metaType.Type); WireType wireType; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, listItemType, out wireType, false, false, false, false) == null) { int num = this.FindOrAddAuto(listItemType, false, false, false); if (num >= 0) { MetaType metaType2 = ((MetaType)this.types[num]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } } else { MetaType metaType2; if (metaType.IsAutoTuple) { MemberInfo[] array; if (MetaType.ResolveTupleConstructor(metaType.Type, out array) != null) { for (int i = 0; i < array.Length; i++) { Type type = null; if (array[i] is PropertyInfo) { type = ((PropertyInfo)array[i]).PropertyType; } else if (array[i] is FieldInfo) { type = ((FieldInfo)array[i]).FieldType; } WireType wireType2; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out wireType2, false, false, false, false) == null) { int num2 = this.FindOrAddAuto(type, false, false, false); if (num2 >= 0) { metaType2 = ((MetaType)this.types[num2]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } } } } else { foreach (ValueMember valueMember in metaType.Fields) { Type type2 = valueMember.ItemType; if (type2 == null) { type2 = valueMember.MemberType; } WireType wireType3; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type2, out wireType3, false, false, false, false) == null) { int num3 = this.FindOrAddAuto(type2, false, false, false); if (num3 >= 0) { metaType2 = ((MetaType)this.types[num3]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } } } if (metaType.HasSubtypes) { SubType[] subtypes = metaType.GetSubtypes(); for (int j = 0; j < subtypes.Length; j++) { SubType subType = subtypes[j]; metaType2 = subType.DerivedType.GetSurrogateOrSelf(); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } metaType2 = metaType.BaseType; if (metaType2 != null) { metaType2 = metaType2.GetSurrogateOrSelf(); } if (metaType2 != null && !list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } }
private ValueMember ApplyDefaultBehaviour(bool isEnum, AttributeFamily family, MemberInfo member, BasicList partialMembers) { if (member == null || (family == AttributeFamily.None && !isEnum)) return null; // nix Type effectiveType; switch (member.MemberType) { case MemberTypes.Field: effectiveType = ((FieldInfo)member).FieldType; break; case MemberTypes.Property: effectiveType = ((PropertyInfo)member).PropertyType; break; default: return null; // nothing doing } int fieldNumber = 0; bool isPacked = false; string name = null; bool isRequired = false; Type itemType = null; Type defaultType = null; ResolveListTypes(effectiveType, ref itemType, ref defaultType); object[] attribs = member.GetCustomAttributes(true); Attribute attrib; DataFormat dataFormat = DataFormat.Default; bool ignore = false; object defaultValue = null; // implicit zero default switch (Type.GetTypeCode(effectiveType)) { case TypeCode.Boolean: defaultValue = false; break; case TypeCode.Decimal: defaultValue = (decimal)0; break; case TypeCode.Single: defaultValue = (float)0; break; case TypeCode.Double: defaultValue = (double)0; break; case TypeCode.Byte: defaultValue = (byte)0; break; case TypeCode.Char: defaultValue = (char)0; break; case TypeCode.Int16: defaultValue = (short)0; break; case TypeCode.Int32: defaultValue = (int)0; break; case TypeCode.Int64: defaultValue = (long)0; break; case TypeCode.SByte: defaultValue = (sbyte)0; break; case TypeCode.UInt16: defaultValue = (ushort)0; break; case TypeCode.UInt32: defaultValue = (uint)0; break; case TypeCode.UInt64: defaultValue = (ulong)0; break; default: if (effectiveType == typeof(TimeSpan)) defaultValue = TimeSpan.Zero; if (effectiveType == typeof(Guid)) defaultValue = Guid.Empty; break; } bool done = false; if (isEnum) { attrib = GetAttribute(attribs, "ProtoBuf.ProtoIgnoreAttribute"); if (attrib != null) { ignore = true; } else { attrib = GetAttribute(attribs, "ProtoBuf.ProtoEnumAttribute"); fieldNumber = Convert.ToInt32(((FieldInfo)member).GetValue(null)); if (attrib != null) { GetFieldName(ref name, attrib, "Name"); if ((bool)attrib.GetType().GetMethod("HasValue").Invoke(attrib, null)) { fieldNumber = (int) GetMemberValue(attrib, "Value"); } } } done = true; } if (!ignore && !done) // always consider ProtoMember { attrib = GetAttribute(attribs, "ProtoBuf.ProtoMemberAttribute"); GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.ProtoIgnoreAttribute"); if (!ignore) { GetFieldNumber(ref fieldNumber, attrib, "Tag"); GetFieldName(ref name, attrib, "Name"); GetFieldBoolean(ref isRequired, attrib, "IsRequired"); GetFieldBoolean(ref isPacked, attrib, "IsPacked"); GetDataFormat(ref dataFormat, attrib, "DataFormat"); done = fieldNumber > 0; } if (!done && partialMembers != null) { foreach (ProtoPartialMemberAttribute ppma in partialMembers) { if (ppma.MemberName == member.Name) { GetFieldNumber(ref fieldNumber, ppma, "Tag"); GetFieldName(ref name, ppma, "Name"); GetFieldBoolean(ref isRequired, ppma, "IsRequired"); GetFieldBoolean(ref isPacked, ppma, "IsPacked"); GetDataFormat(ref dataFormat, ppma, "DataFormat"); if (done = fieldNumber > 0) break; } } } } if (!ignore && !done && HasFamily(family, AttributeFamily.DataContractSerialier)) { attrib = GetAttribute(attribs, "System.Runtime.Serialization.DataMemberAttribute"); GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "Name"); GetFieldBoolean(ref isRequired, attrib, "IsRequired"); done = fieldNumber > 0; } if (!ignore && !done && HasFamily(family, AttributeFamily.XmlSerializer)) { attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlElementAttribute"); GetIgnore(ref ignore, attrib, attribs, "System.Xml.Serialization.XmlIgnoreAttribute"); if (!ignore) { GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "ElementName"); } attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlArrayAttribute"); GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.XmlIgnoreAttribute"); if (!ignore) { GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "ElementName"); } done = fieldNumber > 0; } if (!ignore && (attrib = GetAttribute(attribs, "System.ComponentModel.DefaultValueAttribute")) != null) { defaultValue = GetMemberValue(attrib, "Value"); } ValueMember vm = ((isEnum || fieldNumber > 0) && !ignore) ? new ValueMember(model, type, fieldNumber, member, effectiveType, itemType, defaultType, dataFormat, defaultValue) : null; if (vm != null) { PropertyInfo prop = type.GetProperty(member.Name + "Specified", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, typeof(bool), Helpers.EmptyTypes, null); if (prop != null) { vm.SetSpecified(prop.GetGetMethod(true), prop.GetSetMethod(true)); } else { MethodInfo method = type.GetMethod("ShouldSerialize" + member.Name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Helpers.EmptyTypes, null); if (method != null && method.ReturnType == typeof(bool)) { vm.SetSpecified(method, null); } } if(!Helpers.IsNullOrEmpty(name)) vm.SetName(name); vm.IsPacked = isPacked; vm.IsRequired = isRequired; } return vm; }
/// <summary> /// Fully compiles the current model into a static-compiled serialization dll /// (the serialization dll still requires protobuf-net for support services). /// </summary> /// <remarks>A full compilation is restricted to accessing public types / members</remarks> /// <returns>An instance of the newly created compiled type-model</returns> public TypeModel Compile(CompilerOptions options) { if (options == null) throw new ArgumentNullException("options"); string typeName = options.TypeName; string path = options.OutputPath; BuildAllSerializers(); Freeze(); bool save = !Helpers.IsNullOrEmpty(path); if (Helpers.IsNullOrEmpty(typeName)) { if (save) throw new ArgumentNullException("typeName"); typeName = Guid.NewGuid().ToString(); } string assemblyName, moduleName; if(path == null) { assemblyName = typeName; moduleName = assemblyName + ".dll"; } else { assemblyName = new System.IO.FileInfo(System.IO.Path.GetFileNameWithoutExtension(path)).Name; moduleName = assemblyName + System.IO.Path.GetExtension(path); } #if FEAT_IKVM IKVM.Reflection.AssemblyName an = new IKVM.Reflection.AssemblyName(); an.Name = assemblyName; AssemblyBuilder asm = universe.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save); if(!Helpers.IsNullOrEmpty(options.ImageRuntimeVersion) && options.MetaDataVersion != 0) { asm.__SetImageRuntimeVersion(options.ImageRuntimeVersion, options.MetaDataVersion); } ModuleBuilder module = asm.DefineDynamicModule(moduleName, path); #else AssemblyName an = new AssemblyName(); an.Name = assemblyName; AssemblyBuilder asm = AppDomain.CurrentDomain.DefineDynamicAssembly(an, (save ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run) ); ModuleBuilder module = save ? asm.DefineDynamicModule(moduleName, path) : asm.DefineDynamicModule(moduleName); #endif if (!Helpers.IsNullOrEmpty(options.TargetFrameworkName)) { // get [TargetFramework] from mscorlib/equivalent and burn into the new assembly Type versionAttribType = null; try { // this is best-endeavours only versionAttribType = GetType("System.Runtime.Versioning.TargetFrameworkAttribute", MapType(typeof(string)).Assembly); } catch { /* don't stress */ } if (versionAttribType != null) { PropertyInfo[] props; object[] propValues; if (Helpers.IsNullOrEmpty(options.TargetFrameworkDisplayName)) { props = new PropertyInfo[0]; propValues = new object[0]; } else { props = new PropertyInfo[1] { versionAttribType.GetProperty("FrameworkDisplayName") }; propValues = new object[1] { options.TargetFrameworkDisplayName }; } CustomAttributeBuilder builder = new CustomAttributeBuilder( versionAttribType.GetConstructor(new Type[] { MapType(typeof(string)) }), new object[] { options.TargetFrameworkName }, props, propValues); asm.SetCustomAttribute(builder); } } // copy assembly:InternalsVisibleTo Type internalsVisibleToAttribType = null; #if !FX11 try { internalsVisibleToAttribType = MapType(typeof(System.Runtime.CompilerServices.InternalsVisibleToAttribute)); } catch { /* best endeavors only */ } #endif if (internalsVisibleToAttribType != null) { BasicList internalAssemblies = new BasicList(), consideredAssemblies = new BasicList(); foreach (MetaType metaType in types) { Assembly assembly = metaType.Type.Assembly; if (consideredAssemblies.IndexOfReference(assembly) >= 0) continue; consideredAssemblies.Add(assembly); AttributeMap[] assemblyAttribsMap = AttributeMap.Create(this, assembly); for (int i = 0; i < assemblyAttribsMap.Length; i++) { if (assemblyAttribsMap[i].AttributeType != internalsVisibleToAttribType) continue; object privelegedAssemblyObj; assemblyAttribsMap[i].TryGet("AssemblyName", out privelegedAssemblyObj); string privelegedAssemblyName = privelegedAssemblyObj as string; if (privelegedAssemblyName == assemblyName || Helpers.IsNullOrEmpty(privelegedAssemblyName)) continue; // ignore if (internalAssemblies.IndexOf(new StringFinder(privelegedAssemblyName)) >= 0) continue; // seen it before internalAssemblies.Add(privelegedAssemblyName); CustomAttributeBuilder builder = new CustomAttributeBuilder( internalsVisibleToAttribType.GetConstructor(new Type[] { MapType(typeof(string)) }), new object[] { privelegedAssemblyName }); asm.SetCustomAttribute(builder); } } } Type baseType = MapType(typeof(TypeModel)); TypeAttributes typeAttributes = (baseType.Attributes & ~TypeAttributes.Abstract) | TypeAttributes.Sealed; if(options.Accessibility == Accessibility.Internal) { typeAttributes &= ~TypeAttributes.Public; } TypeBuilder type = module.DefineType(typeName, typeAttributes, baseType); Compiler.CompilerContext ctx; int index = 0; bool hasInheritance = false; SerializerPair[] methodPairs = new SerializerPair[types.Count]; foreach (MetaType metaType in types) { MethodBuilder writeMethod = type.DefineMethod("Write" #if DEBUG + metaType.Type.Name #endif , MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard, MapType(typeof(void)), new Type[] { metaType.Type, MapType(typeof(ProtoWriter)) }); MethodBuilder readMethod = type.DefineMethod("Read" #if DEBUG + metaType.Type.Name #endif , MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard, metaType.Type, new Type[] { metaType.Type, MapType(typeof(ProtoReader)) }); SerializerPair pair = new SerializerPair( GetKey(metaType.Type, true, false), GetKey(metaType.Type, true, true), metaType, writeMethod, readMethod, writeMethod.GetILGenerator(), readMethod.GetILGenerator()); methodPairs[index++] = pair; if (pair.MetaKey != pair.BaseKey) hasInheritance = true; } if (hasInheritance) { Array.Sort(methodPairs); } Compiler.CompilerContext.ILVersion ilVersion = Compiler.CompilerContext.ILVersion.Net2; if (options.MetaDataVersion == 0x10000) { ilVersion = Compiler.CompilerContext.ILVersion.Net1; // old-school! } for(index = 0; index < methodPairs.Length ; index++) { SerializerPair pair = methodPairs[index]; ctx = new Compiler.CompilerContext(pair.SerializeBody, true, true, methodPairs, this, ilVersion, assemblyName); ctx.CheckAccessibility(pair.Deserialize.ReturnType); pair.Type.Serializer.EmitWrite(ctx, Compiler.Local.InputValue); ctx.Return(); ctx = new Compiler.CompilerContext(pair.DeserializeBody, true, false, methodPairs, this, ilVersion, assemblyName); pair.Type.Serializer.EmitRead(ctx, Compiler.Local.InputValue); if (!pair.Type.Serializer.ReturnsValue) { ctx.LoadValue(Compiler.Local.InputValue); } ctx.Return(); } ILGenerator il = Override(type, "GetKeyImpl"); int knownTypesCategory; FieldBuilder knownTypes; Type knownTypesLookupType; const int KnownTypes_Array = 1, KnownTypes_Dictionary = 2, KnownTypes_Hashtable = 3, KnownTypes_ArrayCutoff = 20; if (types.Count <= KnownTypes_ArrayCutoff) { knownTypesCategory = KnownTypes_Array; knownTypesLookupType = MapType(typeof(System.Type[]), true); } else { #if NO_GENERICS knownTypesLookupType = null; #else knownTypesLookupType = MapType(typeof(System.Collections.Generic.Dictionary<System.Type, int>), false); #endif if (knownTypesLookupType == null) { knownTypesLookupType = MapType(typeof(Hashtable), true); knownTypesCategory = KnownTypes_Hashtable; } else { knownTypesCategory = KnownTypes_Dictionary; } } knownTypes = type.DefineField("knownTypes", knownTypesLookupType, FieldAttributes.Private | FieldAttributes.InitOnly | FieldAttributes.Static); switch(knownTypesCategory) { case KnownTypes_Array: { il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldarg_1); // note that Array.IndexOf is not supported under CF il.EmitCall(OpCodes.Callvirt, MapType(typeof(IList)).GetMethod( "IndexOf", new Type[] { MapType(typeof(object)) }), null); if (hasInheritance) { il.DeclareLocal(MapType(typeof(int))); // loc-0 il.Emit(OpCodes.Dup); il.Emit(OpCodes.Stloc_0); BasicList getKeyLabels = new BasicList(); int lastKey = -1; for (int i = 0; i < methodPairs.Length; i++) { if (methodPairs[i].MetaKey == methodPairs[i].BaseKey) break; if (lastKey == methodPairs[i].BaseKey) { // add the last label again getKeyLabels.Add(getKeyLabels[getKeyLabels.Count - 1]); } else { // add a new unique label getKeyLabels.Add(il.DefineLabel()); lastKey = methodPairs[i].BaseKey; } } Label[] subtypeLabels = new Label[getKeyLabels.Count]; getKeyLabels.CopyTo(subtypeLabels, 0); il.Emit(OpCodes.Switch, subtypeLabels); il.Emit(OpCodes.Ldloc_0); // not a sub-type; use the original value il.Emit(OpCodes.Ret); lastKey = -1; // now output the different branches per sub-type (not derived type) for (int i = subtypeLabels.Length - 1; i >= 0; i--) { if (lastKey != methodPairs[i].BaseKey) { lastKey = methodPairs[i].BaseKey; // find the actual base-index for this base-key (i.e. the index of // the base-type) int keyIndex = -1; for (int j = subtypeLabels.Length; j < methodPairs.Length; j++) { if (methodPairs[j].BaseKey == lastKey && methodPairs[j].MetaKey == lastKey) { keyIndex = j; break; } } il.MarkLabel(subtypeLabels[i]); Compiler.CompilerContext.LoadValue(il, keyIndex); il.Emit(OpCodes.Ret); } } } else { il.Emit(OpCodes.Ret); } } break; case KnownTypes_Dictionary: { LocalBuilder result = il.DeclareLocal(MapType(typeof(int))); Label otherwise = il.DefineLabel(); il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloca_S, result); il.EmitCall(OpCodes.Callvirt, knownTypesLookupType.GetMethod("TryGetValue", BindingFlags.Instance | BindingFlags.Public), null); il.Emit(OpCodes.Brfalse_S, otherwise); il.Emit(OpCodes.Ldloc_S, result); il.Emit(OpCodes.Ret); il.MarkLabel(otherwise); il.Emit(OpCodes.Ldc_I4_M1); il.Emit(OpCodes.Ret); } break; case KnownTypes_Hashtable: { Label otherwise = il.DefineLabel(); il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldarg_1); il.EmitCall(OpCodes.Callvirt, knownTypesLookupType.GetProperty("Item").GetGetMethod(), null); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Brfalse_S, otherwise); #if FX11 il.Emit(OpCodes.Unbox, MapType(typeof(int))); il.Emit(OpCodes.Ldobj, MapType(typeof(int))); #else if (ilVersion == Compiler.CompilerContext.ILVersion.Net1) { il.Emit(OpCodes.Unbox, MapType(typeof(int))); il.Emit(OpCodes.Ldobj, MapType(typeof(int))); } else { il.Emit(OpCodes.Unbox_Any, MapType(typeof(int))); } #endif il.Emit(OpCodes.Ret); il.MarkLabel(otherwise); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldc_I4_M1); il.Emit(OpCodes.Ret); } break; default: throw new InvalidOperationException(); } il = Override(type, "Serialize"); ctx = new Compiler.CompilerContext(il, false, true, methodPairs, this, ilVersion, assemblyName); // arg0 = this, arg1 = key, arg2=obj, arg3=dest Label[] jumpTable = new Label[types.Count]; for (int i = 0; i < jumpTable.Length; i++) { jumpTable[i] = il.DefineLabel(); } il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Switch, jumpTable); ctx.Return(); for (int i = 0; i < jumpTable.Length; i++) { SerializerPair pair = methodPairs[i]; il.MarkLabel(jumpTable[i]); il.Emit(OpCodes.Ldarg_2); ctx.CastFromObject(pair.Type.Type); il.Emit(OpCodes.Ldarg_3); il.EmitCall(OpCodes.Call, pair.Serialize, null); ctx.Return(); } il = Override(type, "Deserialize"); ctx = new Compiler.CompilerContext(il, false, false, methodPairs, this, ilVersion, assemblyName); // arg0 = this, arg1 = key, arg2=obj, arg3=source for (int i = 0; i < jumpTable.Length; i++) { jumpTable[i] = il.DefineLabel(); } il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Switch, jumpTable); ctx.LoadNullRef(); ctx.Return(); for (int i = 0; i < jumpTable.Length; i++) { SerializerPair pair = methodPairs[i]; il.MarkLabel(jumpTable[i]); Type keyType = pair.Type.Type; if (keyType.IsValueType) { il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.EmitCall(OpCodes.Call, EmitBoxedSerializer(type, i, keyType, methodPairs, this, ilVersion, assemblyName), null); ctx.Return(); } else { il.Emit(OpCodes.Ldarg_2); ctx.CastFromObject(keyType); il.Emit(OpCodes.Ldarg_3); il.EmitCall(OpCodes.Call, pair.Deserialize, null); ctx.Return(); } } type.DefineDefaultConstructor(MethodAttributes.Public); il = type.DefineTypeInitializer().GetILGenerator(); switch (knownTypesCategory) { case KnownTypes_Array: { Compiler.CompilerContext.LoadValue(il, types.Count); il.Emit(OpCodes.Newarr, ctx.MapType(typeof(System.Type))); index = 0; foreach (SerializerPair pair in methodPairs) { il.Emit(OpCodes.Dup); Compiler.CompilerContext.LoadValue(il, index); il.Emit(OpCodes.Ldtoken, pair.Type.Type); il.EmitCall(OpCodes.Call, ctx.MapType(typeof(System.Type)).GetMethod("GetTypeFromHandle"), null); il.Emit(OpCodes.Stelem_Ref); index++; } il.Emit(OpCodes.Stsfld, knownTypes); il.Emit(OpCodes.Ret); } break; case KnownTypes_Dictionary: { Compiler.CompilerContext.LoadValue(il, types.Count); LocalBuilder loc = il.DeclareLocal(knownTypesLookupType); il.Emit(OpCodes.Newobj, knownTypesLookupType.GetConstructor(new Type[] { MapType(typeof(int)) })); il.Emit(OpCodes.Stsfld, knownTypes); int typeIndex = 0; foreach (SerializerPair pair in methodPairs) { il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldtoken, pair.Type.Type); il.EmitCall(OpCodes.Call, ctx.MapType(typeof(System.Type)).GetMethod("GetTypeFromHandle"), null); int keyIndex = typeIndex++, lastKey = pair.BaseKey; if (lastKey != pair.MetaKey) // not a base-type; need to give the index of the base-type { keyIndex = -1; // assume epic fail for (int j = 0; j < methodPairs.Length; j++) { if (methodPairs[j].BaseKey == lastKey && methodPairs[j].MetaKey == lastKey) { keyIndex = j; break; } } } Compiler.CompilerContext.LoadValue(il, keyIndex); il.EmitCall(OpCodes.Callvirt, knownTypesLookupType.GetMethod("Add", new Type[] { MapType(typeof(System.Type)), MapType(typeof(int)) }), null); } il.Emit(OpCodes.Ret); } break; case KnownTypes_Hashtable: { Compiler.CompilerContext.LoadValue(il, types.Count); il.Emit(OpCodes.Newobj, knownTypesLookupType.GetConstructor(new Type[] { MapType(typeof(int)) })); il.Emit(OpCodes.Stsfld, knownTypes); int typeIndex = 0; foreach (SerializerPair pair in methodPairs) { il.Emit(OpCodes.Ldsfld, knownTypes); il.Emit(OpCodes.Ldtoken, pair.Type.Type); il.EmitCall(OpCodes.Call, ctx.MapType(typeof(System.Type)).GetMethod("GetTypeFromHandle"), null); int keyIndex = typeIndex++, lastKey = pair.BaseKey; if (lastKey != pair.MetaKey) // not a base-type; need to give the index of the base-type { keyIndex = -1; // assume epic fail for (int j = 0; j < methodPairs.Length; j++) { if (methodPairs[j].BaseKey == lastKey && methodPairs[j].MetaKey == lastKey) { keyIndex = j; break; } } } Compiler.CompilerContext.LoadValue(il, keyIndex); il.Emit(OpCodes.Box, MapType(typeof(int))); il.EmitCall(OpCodes.Callvirt, knownTypesLookupType.GetMethod("Add", new Type[] { MapType(typeof(object)), MapType(typeof(object)) }), null); } il.Emit(OpCodes.Ret); } break; default: throw new InvalidOperationException(); } Type finalType = type.CreateType(); if(!Helpers.IsNullOrEmpty(path)) { asm.Save(path); Helpers.DebugWriteLine("Wrote dll:" + path); } #if FEAT_IKVM return null; #else return (TypeModel)Activator.CreateInstance(finalType); #endif }
private IProtoTypeSerializer BuildSerializer() { if (surrogate != null) { MetaType mt = model[surrogate], mtBase; while ((mtBase = mt.baseType) != null) { mt = mtBase; } return(new SurrogateSerializer(type, surrogate, mt.Serializer)); } Type itemType = TypeModel.GetListItemType(type); if (itemType != null) { ValueMember fakeMember = new ValueMember(model, 1, type, itemType, type, DataFormat.Default); return(new TypeSerializer(type, new int[] { 1 }, new IProtoSerializer[] { fakeMember.Serializer }, null, true, true, null, constructType)); } fields.Trim(); int fieldCount = fields.Count; int subTypeCount = subTypes == null ? 0 : subTypes.Count; int[] fieldNumbers = new int[fieldCount + subTypeCount]; IProtoSerializer[] serializers = new IProtoSerializer[fieldCount + subTypeCount]; int i = 0; if (subTypeCount != 0) { foreach (SubType subType in subTypes) { fieldNumbers[i] = subType.FieldNumber; serializers[i++] = subType.Serializer; } } if (fieldCount != 0) { foreach (ValueMember member in fields) { fieldNumbers[i] = member.FieldNumber; serializers[i++] = member.Serializer; } } BasicList baseCtorCallbacks = null; MetaType tmp = BaseType; while (tmp != null) { MethodInfo method = tmp.HasCallbacks ? tmp.Callbacks.BeforeDeserialize : null; if (method != null) { if (baseCtorCallbacks == null) { baseCtorCallbacks = new BasicList(); } baseCtorCallbacks.Add(method); } tmp = tmp.BaseType; } MethodInfo[] arr = null; if (baseCtorCallbacks != null) { arr = new MethodInfo[baseCtorCallbacks.Count]; baseCtorCallbacks.CopyTo(arr, 0); Array.Reverse(arr); } return(new TypeSerializer(type, fieldNumbers, serializers, arr, baseType == null, UseConstructor, callbacks, constructType)); }
// Token: 0x06000369 RID: 873 RVA: 0x00012780 File Offset: 0x00010980 public override string GetSchema(Type type) { BasicList basicList = new BasicList(); MetaType metaType = null; bool flag = false; if (type == null) { foreach (object obj in this.types) { MetaType surrogateOrBaseOrSelf = ((MetaType)obj).GetSurrogateOrBaseOrSelf(false); if (!basicList.Contains(surrogateOrBaseOrSelf)) { basicList.Add(surrogateOrBaseOrSelf); this.CascadeDependents(basicList, surrogateOrBaseOrSelf); } } } else { Type underlyingType = Helpers.GetUnderlyingType(type); if (underlyingType != null) { type = underlyingType; } WireType wireType; flag = (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out wireType, false, false, false, false) != null); if (!flag) { int num = this.FindOrAddAuto(type, false, false, false); if (num < 0) { throw new ArgumentException("The type specified is not a contract-type", "type"); } metaType = ((MetaType)this.types[num]).GetSurrogateOrBaseOrSelf(false); basicList.Add(metaType); this.CascadeDependents(basicList, metaType); } } StringBuilder stringBuilder = new StringBuilder(); string text = null; if (!flag) { foreach (object obj2 in ((IEnumerable)((metaType == null) ? this.types : basicList))) { MetaType metaType2 = (MetaType)obj2; if (!metaType2.IsList) { string @namespace = metaType2.Type.Namespace; if (!Helpers.IsNullOrEmpty(@namespace) && [email protected]("System.")) { if (text == null) { text = @namespace; } else if (!(text == @namespace)) { text = null; break; } } } } } if (!Helpers.IsNullOrEmpty(text)) { stringBuilder.Append("package ").Append(text).Append(';'); Helpers.AppendLine(stringBuilder); } bool flag2 = false; StringBuilder stringBuilder2 = new StringBuilder(); MetaType[] array = new MetaType[basicList.Count]; basicList.CopyTo(array, 0); Array.Sort <MetaType>(array, MetaType.Comparer.Default); if (flag) { Helpers.AppendLine(stringBuilder2).Append("message ").Append(type.Name).Append(" {"); MetaType.NewLine(stringBuilder2, 1).Append("optional ").Append(this.GetSchemaTypeName(type, DataFormat.Default, false, false, ref flag2)).Append(" value = 1;"); Helpers.AppendLine(stringBuilder2).Append('}'); } else { foreach (MetaType metaType3 in array) { if (!metaType3.IsList || metaType3 == metaType) { metaType3.WriteSchema(stringBuilder2, 0, ref flag2); } } } if (flag2) { stringBuilder.Append("import \"bcl.proto\"; // schema for protobuf-net's handling of core .NET types"); Helpers.AppendLine(stringBuilder); } return(Helpers.AppendLine(stringBuilder.Append(stringBuilder2)).ToString()); }
private void CascadeDependents(BasicList list, MetaType metaType) { if (metaType.IsList) { Type listItemType = TypeModel.GetListItemType(this, metaType.Type); WireType wireType; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, listItemType, out wireType, false, false, false, false) == null) { int num = this.FindOrAddAuto(listItemType, false, false, false); if (num >= 0) { MetaType metaType2 = ((MetaType)this.types[num]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } } else { MetaType metaType2; if (metaType.IsAutoTuple) { MemberInfo[] array; if (MetaType.ResolveTupleConstructor(metaType.Type, out array) != null) { for (int i = 0; i < array.Length; i++) { Type type = null; if (array[i] is PropertyInfo) { type = ((PropertyInfo)array[i]).get_PropertyType(); } else if (array[i] is FieldInfo) { type = ((FieldInfo)array[i]).get_FieldType(); } WireType wireType2; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out wireType2, false, false, false, false) == null) { int num2 = this.FindOrAddAuto(type, false, false, false); if (num2 >= 0) { metaType2 = ((MetaType)this.types[num2]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } } } } else { IEnumerator enumerator = metaType.Fields.GetEnumerator(); try { while (enumerator.MoveNext()) { ValueMember valueMember = (ValueMember)enumerator.get_Current(); Type type2 = valueMember.ItemType; if (type2 == null) { type2 = valueMember.MemberType; } WireType wireType3; if (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type2, out wireType3, false, false, false, false) == null) { int num3 = this.FindOrAddAuto(type2, false, false, false); if (num3 >= 0) { metaType2 = ((MetaType)this.types[num3]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } } if (metaType.HasSubtypes) { SubType[] subtypes = metaType.GetSubtypes(); for (int j = 0; j < subtypes.Length; j++) { SubType subType = subtypes[j]; metaType2 = subType.DerivedType.GetSurrogateOrSelf(); if (!list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } } metaType2 = metaType.BaseType; if (metaType2 != null) { metaType2 = metaType2.GetSurrogateOrSelf(); } if (metaType2 != null && !list.Contains(metaType2)) { list.Add(metaType2); this.CascadeDependents(list, metaType2); } } }
public override string GetSchema(Type type) { BasicList basicList = new BasicList(); MetaType metaType = null; bool flag = false; if (type == null) { BasicList.NodeEnumerator enumerator = this.types.GetEnumerator(); while (enumerator.MoveNext()) { MetaType metaType2 = (MetaType)enumerator.Current; MetaType surrogateOrBaseOrSelf = metaType2.GetSurrogateOrBaseOrSelf(false); if (!basicList.Contains(surrogateOrBaseOrSelf)) { basicList.Add(surrogateOrBaseOrSelf); this.CascadeDependents(basicList, surrogateOrBaseOrSelf); } } } else { Type underlyingType = Helpers.GetUnderlyingType(type); if (underlyingType != null) { type = underlyingType; } WireType wireType; flag = (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out wireType, false, false, false, false) != null); if (!flag) { int num = this.FindOrAddAuto(type, false, false, false); if (num < 0) { throw new ArgumentException("The type specified is not a contract-type", "type"); } metaType = ((MetaType)this.types[num]).GetSurrogateOrBaseOrSelf(false); basicList.Add(metaType); this.CascadeDependents(basicList, metaType); } } StringBuilder stringBuilder = new StringBuilder(); string text = null; if (!flag) { IEnumerable enumerable = (metaType != null) ? basicList : this.types; IEnumerator enumerator2 = enumerable.GetEnumerator(); try { while (enumerator2.MoveNext()) { MetaType metaType3 = (MetaType)enumerator2.get_Current(); if (!metaType3.IsList) { string @namespace = metaType3.Type.get_Namespace(); if (!Helpers.IsNullOrEmpty(@namespace)) { if ([email protected]("System.")) { if (text == null) { text = @namespace; } else if (!(text == @namespace)) { text = null; break; } } } } } } finally { IDisposable disposable = enumerator2 as IDisposable; if (disposable != null) { disposable.Dispose(); } } } if (!Helpers.IsNullOrEmpty(text)) { stringBuilder.Append("package ").Append(text).Append(';'); Helpers.AppendLine(stringBuilder); } bool flag2 = false; StringBuilder stringBuilder2 = new StringBuilder(); MetaType[] array = new MetaType[basicList.Count]; basicList.CopyTo(array, 0); Array.Sort <MetaType>(array, MetaType.Comparer.Default); if (flag) { Helpers.AppendLine(stringBuilder2).Append("message ").Append(type.get_Name()).Append(" {"); MetaType.NewLine(stringBuilder2, 1).Append("optional ").Append(this.GetSchemaTypeName(type, DataFormat.Default, false, false, ref flag2)).Append(" value = 1;"); Helpers.AppendLine(stringBuilder2).Append('}'); } else { for (int i = 0; i < array.Length; i++) { MetaType metaType4 = array[i]; if (!metaType4.IsList || metaType4 == metaType) { metaType4.WriteSchema(stringBuilder2, 0, ref flag2); } } } if (flag2) { stringBuilder.Append("import \"bcl.proto\"; // schema for protobuf-net's handling of core .NET types"); Helpers.AppendLine(stringBuilder); } return(Helpers.AppendLine(stringBuilder.Append(stringBuilder2)).ToString()); }
internal static Type GetListItemType(Type listType) { Helpers.DebugAssert(listType != null); if (listType == typeof(string) || listType.IsArray || !typeof(IEnumerable).IsAssignableFrom(listType)) return null; BasicList candidates = new BasicList(); candidates.Add(typeof(object)); foreach (MethodInfo method in listType.GetMethods(BindingFlags.Public | BindingFlags.Instance)) { if (method.Name != "Add") continue; ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 1 && !candidates.Contains(parameters[0].ParameterType)) { candidates.Add(parameters[0].ParameterType); } } foreach (Type iType in listType.GetInterfaces()) { if (iType.IsGenericType && iType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.ICollection<>)) { Type[] iTypeArgs = iType.GetGenericArguments(); if (!candidates.Contains(iTypeArgs[0])) { candidates.Add(iTypeArgs[0]); } } } // more convenient GetProperty overload not supported on all platforms foreach (PropertyInfo indexer in listType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (indexer.Name != "Item" || candidates.Contains(indexer.PropertyType)) continue; ParameterInfo[] args = indexer.GetIndexParameters(); if (args.Length != 1 || args[0].ParameterType != typeof(int)) continue; candidates.Add(indexer.PropertyType); } switch (candidates.Count) { case 1: return null; case 2: return (Type)candidates[1]; case 3: if (CheckDictionaryAccessors((Type)candidates[1], (Type)candidates[2])) return (Type)candidates[1]; if (CheckDictionaryAccessors((Type)candidates[2], (Type)candidates[1])) return (Type)candidates[2]; break; } return null; }
internal int IndexOf(BasicList.MatchPredicate predicate, object ctx) { return this.head.IndexOf(predicate, ctx); }
private BasicList GetNestedListHierarchy(Type type) { BasicList list = new BasicList(); Type itemT; Type defaultT; do { itemT = null; defaultT = null; MetaType.ResolveListTypes(type, ref itemT, ref defaultT); list.Add(new NestedItem(type, itemT, defaultT)); type = itemT; } while (itemT != null); return list; }
internal int IndexOf(BasicList.MatchPredicate predicate, object ctx) { for (int i = 0; i < this.length; i++) { if (predicate(this.data[i], ctx)) { return i; } } return -1; }
private bool HasAutoDynamicHandling(BasicList nestedHierarchy) { int hierarchyCount = nestedHierarchy.Count; for (int i = 0; i < hierarchyCount - 1; i++) { NestedItem item = (NestedItem) nestedHierarchy[i]; MetaType metaType = model.FindWithoutAdd(item.Type); if (metaType != null && metaType.AutoDynamicHandling) { return true; } } return false; }
/// <summary> /// Suggest a .proto definition for the given type /// </summary> /// <param name="type">The type to generate a .proto definition for, or <c>null</c> to generate a .proto that represents the entire model</param> /// <returns>The .proto definition as a string</returns> public override string GetSchema(Type type) { BasicList requiredTypes = new BasicList(); MetaType primaryType = null; bool isInbuiltType = false; if (type == null) { // generate for the entire model foreach(MetaType meta in types) { MetaType tmp = meta.GetSurrogateOrBaseOrSelf(false); if (!requiredTypes.Contains(tmp)) { // ^^^ note that the type might have been added as a descendent requiredTypes.Add(tmp); CascadeDependents(requiredTypes, tmp); } } } else { Type tmp = Helpers.GetUnderlyingType(type); if (tmp != null) type = tmp; WireType defaultWireType; isInbuiltType = (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out defaultWireType, false, false, false, false) != null); if (!isInbuiltType) { //Agenerate just relative to the supplied type int index = FindOrAddAuto(type, false, false, false); if (index < 0) throw new ArgumentException("The type specified is not a contract-type", "type"); // get the required types primaryType = ((MetaType)types[index]).GetSurrogateOrBaseOrSelf(false); requiredTypes.Add(primaryType); CascadeDependents(requiredTypes, primaryType); } } // use the provided type's namespace for the "package" StringBuilder headerBuilder = new StringBuilder(); string package = null; if (!isInbuiltType) { IEnumerable typesForNamespace = primaryType == null ? types : requiredTypes; foreach (MetaType meta in typesForNamespace) { if (meta.IsList) continue; string tmp = meta.Type.Namespace; if (!Helpers.IsNullOrEmpty(tmp)) { if (tmp.StartsWith("System.")) continue; if (package == null) { // haven't seen any suggestions yet package = tmp; } else if (package == tmp) { // that's fine; a repeat of the one we already saw } else { // something else; have confliucting suggestions; abort package = null; break; } } } } if (!Helpers.IsNullOrEmpty(package)) { headerBuilder.Append("package ").Append(package).Append(';'); Helpers.AppendLine(headerBuilder); } bool requiresBclImport = false; StringBuilder bodyBuilder = new StringBuilder(); // sort them by schema-name MetaType[] metaTypesArr = new MetaType[requiredTypes.Count]; requiredTypes.CopyTo(metaTypesArr, 0); Array.Sort(metaTypesArr, MetaType.Comparer.Default); // write the messages if (isInbuiltType) { Helpers.AppendLine(bodyBuilder).Append("message ").Append(type.Name).Append(" {"); MetaType.NewLine(bodyBuilder, 1).Append("optional ").Append(GetSchemaTypeName(type, DataFormat.Default, false, false, ref requiresBclImport)) .Append(" value = 1;"); Helpers.AppendLine(bodyBuilder).Append('}'); } else { for (int i = 0; i < metaTypesArr.Length; i++) { MetaType tmp = metaTypesArr[i]; if (tmp.IsList && tmp != primaryType) continue; tmp.WriteSchema(bodyBuilder, 0, ref requiresBclImport); } } if (requiresBclImport) { headerBuilder.Append("import \"bcl.proto\"; // schema for protobuf-net's handling of core .NET types"); Helpers.AppendLine(headerBuilder); } return Helpers.AppendLine(headerBuilder.Append(bodyBuilder)).ToString(); }
private IProtoSerializer GetNestedSerializer(Type type, out WireType wireType) { MetaType metaType = model.FindWithoutAdd(type); BasicList hierarchy = GetNestedListHierarchy(type); if (hierarchy.Count > 1 && metaType != null && metaType.IgnoreListHandling) { hierarchy = new BasicList(); hierarchy.Add(new NestedItem(type, null, null)); } return GetNestedSerializer(hierarchy, out wireType); }
private void CascadeDependents(BasicList list, MetaType metaType) { MetaType tmp; if (metaType.IsList) { Type itemType = TypeModel.GetListItemType(this, metaType.Type); WireType defaultWireType; IProtoSerializer coreSerializer = ValueMember.TryGetCoreSerializer(this, DataFormat.Default, itemType, out defaultWireType, false, false, false, false); if (coreSerializer == null) { int index = FindOrAddAuto(itemType, false, false, false); if (index >= 0) { tmp = ((MetaType)types[index]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(tmp)) { // could perhaps also implement as a queue, but this should work OK for sane models list.Add(tmp); CascadeDependents(list, tmp); } } } } else { if (metaType.IsAutoTuple) { MemberInfo[] mapping; if(MetaType.ResolveTupleConstructor(metaType.Type, out mapping) != null) { for (int i = 0; i < mapping.Length; i++) { Type type = null; if (mapping[i] is PropertyInfo) type = ((PropertyInfo)mapping[i]).PropertyType; else if (mapping[i] is FieldInfo) type = ((FieldInfo)mapping[i]).FieldType; WireType defaultWireType; IProtoSerializer coreSerializer = ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out defaultWireType, false, false, false, false); if (coreSerializer == null) { int index = FindOrAddAuto(type, false, false, false); if (index >= 0) { tmp = ((MetaType)types[index]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(tmp)) { // could perhaps also implement as a queue, but this should work OK for sane models list.Add(tmp); CascadeDependents(list, tmp); } } } } } } else { foreach (ValueMember member in metaType.Fields) { Type type = member.ItemType; if (type == null) type = member.MemberType; WireType defaultWireType; IProtoSerializer coreSerializer = ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out defaultWireType, false, false, false, false); if (coreSerializer == null) { // is an interesting type int index = FindOrAddAuto(type, false, false, false); if (index >= 0) { tmp = ((MetaType)types[index]).GetSurrogateOrBaseOrSelf(false); if (!list.Contains(tmp)) { // could perhaps also implement as a queue, but this should work OK for sane models list.Add(tmp); CascadeDependents(list, tmp); } } } } } if (metaType.HasSubtypes) { foreach (SubType subType in metaType.GetSubtypes()) { tmp = subType.DerivedType.GetSurrogateOrSelf(); // note: exclude base-types! if (!list.Contains(tmp)) { list.Add(tmp); CascadeDependents(list, tmp); } } } tmp = metaType.BaseType; if (tmp != null) tmp = tmp.GetSurrogateOrSelf(); // note: already walking base-types; exclude base if (tmp != null && !list.Contains(tmp)) { list.Add(tmp); CascadeDependents(list, tmp); } } }
private IProtoSerializer GetNestedSerializer(BasicList nestedHierarchy, out WireType wireType) { IProtoSerializer ser = null; int listCount = nestedHierarchy.Count; wireType = WireType.None; bool hasAutoDynamicHandling = HasAutoDynamicHandling(nestedHierarchy); for (int i = listCount - 1; i >= 0; i--) { NestedItem item = (NestedItem)nestedHierarchy[i]; if (item.ItemType == null) { bool isDynamic = dynamicType; bool requiresDynamic = item.Type.IsInterface || item.Type == typeof (object); if (!isDynamic && autoDynamicType && requiresDynamic) { isDynamic = true; } else if (hasAutoDynamicHandling && requiresDynamic) { // for now just set isDynamic to true isDynamic = true; } ser = TryGetCoreSerializer(model, dataFormat, item.Type, out wireType, asReference, /*dynamicType*/isDynamic, OverwriteList, false, SupportNull); if (ser == null) throw new InvalidOperationException("No serializer defined for type: " + item.Type.FullName); if (listCount == 1) { ser = new TagDecorator(fieldNumber, wireType, IsStrict, ser); } } else { if (SupportNull) { if (IsPacked) { throw new NotSupportedException("Packed encodings cannot support null values"); } ser = new TagDecorator(NullDecorator.Tag, wireType, IsStrict, ser); ser = new NullDecorator(ser); ser = new TagDecorator(fieldNumber, WireType.StartGroup, false, ser); } else { ser = new TagDecorator(fieldNumber, wireType, IsStrict, ser); } bool nested = listCount > 2 && i >= 1; if (item.Type.IsArray) { ser = new ArrayDecorator(ser, fieldNumber, IsPacked, wireType, item.Type, OverwriteList, SupportNull, AsReference, nested); } else { ser = new ListDecorator(item.Type, item.DefaultType, ser, fieldNumber, IsPacked, wireType, member == null || PropertyDecorator.CanWrite(member), OverwriteList, SupportNull, AsReference, nested, isValueMemberForCollectionBasedTypes); } } } return ser; }
public override string GetSchema(Type type) { BasicList basicList = new BasicList(); MetaType metaType = null; bool flag = false; if (type == null) { BasicList.NodeEnumerator enumerator = this.types.GetEnumerator(); while (enumerator.MoveNext()) { MetaType metaType2 = (MetaType)enumerator.Current; MetaType surrogateOrBaseOrSelf = metaType2.GetSurrogateOrBaseOrSelf(false); if (!basicList.Contains(surrogateOrBaseOrSelf)) { basicList.Add(surrogateOrBaseOrSelf); this.CascadeDependents(basicList, surrogateOrBaseOrSelf); } } } else { Type underlyingType = Helpers.GetUnderlyingType(type); if (underlyingType != null) { type = underlyingType; } WireType wireType; flag = (ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out wireType, false, false, false, false) != null); if (!flag) { int num = this.FindOrAddAuto(type, false, false, false); if (num < 0) { throw new ArgumentException("The type specified is not a contract-type", "type"); } metaType = ((MetaType)this.types[num]).GetSurrogateOrBaseOrSelf(false); basicList.Add(metaType); this.CascadeDependents(basicList, metaType); } } StringBuilder stringBuilder = new StringBuilder(); string text = null; if (!flag) { IEnumerable enumerable = (metaType != null) ? basicList : this.types; foreach (MetaType metaType3 in enumerable) { if (!metaType3.IsList) { string @namespace = metaType3.Type.Namespace; if (!Helpers.IsNullOrEmpty(@namespace)) { if ([email protected]("System.")) { if (text == null) { text = @namespace; } else if (!(text == @namespace)) { text = null; break; } } } } } } if (!Helpers.IsNullOrEmpty(text)) { stringBuilder.Append("package ").Append(text).Append(';'); Helpers.AppendLine(stringBuilder); } bool flag2 = false; StringBuilder stringBuilder2 = new StringBuilder(); MetaType[] array = new MetaType[basicList.Count]; basicList.CopyTo(array, 0); Array.Sort<MetaType>(array, MetaType.Comparer.Default); if (flag) { Helpers.AppendLine(stringBuilder2).Append("message ").Append(type.Name).Append(" {"); MetaType.NewLine(stringBuilder2, 1).Append("optional ").Append(this.GetSchemaTypeName(type, DataFormat.Default, false, false, ref flag2)).Append(" value = 1;"); Helpers.AppendLine(stringBuilder2).Append('}'); } else { for (int i = 0; i < array.Length; i++) { MetaType metaType4 = array[i]; if (!metaType4.IsList || metaType4 == metaType) { metaType4.WriteSchema(stringBuilder2, 0, ref flag2); } } } if (flag2) { stringBuilder.Append("import \"bcl.proto\"; // schema for protobuf-net's handling of core .NET types"); Helpers.AppendLine(stringBuilder); } return Helpers.AppendLine(stringBuilder.Append(stringBuilder2)).ToString(); }
public override object Read(object value, ProtoReader source) { int field = source.FieldNumber; BasicList list = new BasicList(); if (packedWireType != WireType.None && source.WireType == WireType.String) { SubItemToken token = ProtoReader.StartSubItem(source); while (ProtoReader.HasSubValue(packedWireType, source)) { list.Add(Tail.Read(null, source)); } ProtoReader.EndSubItem(token, source); } else { do { list.Add(Tail.Read(null, source)); } while (source.TryReadFieldHeader(field)); } int oldLen = AppendToCollection ? ((value == null ? 0 : ((Array)value).Length)) : 0; Array result = Array.CreateInstance(itemType, oldLen + list.Count); if (oldLen != 0) ((Array)value).CopyTo(result, 0); list.CopyTo(result, oldLen); return result; }
internal void ApplyDefaultBehaviour() { if (type.BaseType != null && model.FindWithoutAdd(type.BaseType) == null && GetContractFamily(type.BaseType, null) != MetaType.AttributeFamily.None) { model.FindOrAddAuto(type.BaseType, true, false, false); } object[] typeAttribs = type.GetCustomAttributes(true); AttributeFamily family = GetContractFamily(type, typeAttribs); bool isEnum = type.IsEnum; if (family == AttributeFamily.None && !isEnum) { return; // and you'd like me to do what, exactly? } BasicList partialIgnores = null, partialMembers = null; int dataMemberOffset = 0, implicitFirstTag = 1; bool inferTagByName = model.InferTagFromNameDefault; ImplicitFields implicitMode = ImplicitFields.None; for (int i = 0; i < typeAttribs.Length; i++) { Attribute item = (Attribute)typeAttribs[i]; if (!isEnum && item is ProtoIncludeAttribute) { ProtoIncludeAttribute pia = (ProtoIncludeAttribute)item; AddSubType(pia.Tag, pia.KnownType); } if (item is ProtoPartialIgnoreAttribute) { if (partialIgnores == null) { partialIgnores = new BasicList(); } partialIgnores.Add(((ProtoPartialIgnoreAttribute)item).MemberName); } if (!isEnum && item is ProtoPartialMemberAttribute) { if (partialMembers == null) { partialMembers = new BasicList(); } partialMembers.Add(item); } if (!isEnum && item is ProtoContractAttribute) { ProtoContractAttribute pca = (ProtoContractAttribute)item; dataMemberOffset = pca.DataMemberOffset; if (pca.InferTagFromNameHasValue) { inferTagByName = pca.InferTagFromName; } implicitMode = pca.ImplicitFields; UseConstructor = !pca.SkipConstructor; if (pca.ImplicitFirstTag > 0) { implicitFirstTag = pca.ImplicitFirstTag; } } } if (implicitMode != ImplicitFields.None) { family &= AttributeFamily.ProtoBuf; // with implicit fields, **only** proto attributes are important } MethodInfo[] callbacks = null; BasicList members = new BasicList(); foreach (MemberInfo member in type.GetMembers(isEnum ? BindingFlags.Public | BindingFlags.Static : BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (member.DeclaringType != type) { continue; } if (member.IsDefined(typeof(ProtoIgnoreAttribute), true)) { continue; } if (partialIgnores != null && partialIgnores.Contains(member.Name)) { continue; } bool forced = false, isPublic, isField; Type effectiveType; switch (member.MemberType) { case MemberTypes.Property: PropertyInfo property = (PropertyInfo)member; effectiveType = property.PropertyType; isPublic = property.GetGetMethod(false) != null; isField = false; goto ProcessMember; case MemberTypes.Field: FieldInfo field = (FieldInfo)member; effectiveType = field.FieldType; isPublic = field.IsPublic; isField = true; ProcessMember: switch (implicitMode) { case ImplicitFields.AllFields: if (isField) { forced = true; } break; case ImplicitFields.AllPublic: if (isPublic) { forced = true; } break; } if (effectiveType.IsSubclassOf(typeof(Delegate))) { continue; // we just don't like delegate types ;p } ProtoMemberAttribute normalizedAttribute = NormalizeProtoMember(member, family, forced, isEnum, partialMembers, dataMemberOffset, inferTagByName); if (normalizedAttribute != null) { members.Add(normalizedAttribute); } break; case MemberTypes.Method: if (isEnum) { continue; } MethodInfo method = (MethodInfo)member; object[] memberAttribs = Attribute.GetCustomAttributes(method); if (memberAttribs != null && memberAttribs.Length > 0) { CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeSerializationAttribute", ref callbacks, 0); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterSerializationAttribute", ref callbacks, 1); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeDeserializationAttribute", ref callbacks, 2); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterDeserializationAttribute", ref callbacks, 3); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializingAttribute", ref callbacks, 4); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializedAttribute", ref callbacks, 5); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializingAttribute", ref callbacks, 6); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializedAttribute", ref callbacks, 7); } break; } } ProtoMemberAttribute[] arr = new ProtoMemberAttribute[members.Count]; members.CopyTo(arr, 0); if (inferTagByName || implicitMode != ImplicitFields.None) { Array.Sort(arr); int nextTag = implicitFirstTag; foreach (ProtoMemberAttribute normalizedAttribute in arr) { if (!normalizedAttribute.TagIsPinned) // if ProtoMember etc sets a tag, we'll trust it { normalizedAttribute.Rebase(nextTag++); } } } foreach (ProtoMemberAttribute normalizedAttribute in arr) { ValueMember vm = ApplyDefaultBehaviour(isEnum, normalizedAttribute); if (vm != null) { Add(vm); } } if (callbacks != null) { SetCallbacks(Coalesce(callbacks, 0, 4), Coalesce(callbacks, 1, 5), Coalesce(callbacks, 2, 6), Coalesce(callbacks, 3, 7)); } }
internal void ApplyDefaultBehaviour() { if (model.FindWithoutAdd(type.BaseType) == null && GetContractFamily(type.BaseType, null) != MetaType.AttributeFamily.None) { model.FindOrAddAuto(type.BaseType, true, false, false); } object[] typeAttribs = type.GetCustomAttributes(true); AttributeFamily family = GetContractFamily(type, typeAttribs); bool isEnum = type.IsEnum; if (family == AttributeFamily.None && !isEnum) { return; // and you'd like me to do what, exactly? } BasicList partialIgnores = null, partialMembers = null; for (int i = 0; i < typeAttribs.Length; i++) { if (!isEnum && typeAttribs[i] is ProtoIncludeAttribute) { ProtoIncludeAttribute pia = (ProtoIncludeAttribute)typeAttribs[i]; AddSubType(pia.Tag, pia.KnownType); } if (typeAttribs[i] is ProtoPartialIgnoreAttribute) { if (partialIgnores == null) { partialIgnores = new BasicList(); } partialIgnores.Add(((ProtoPartialIgnoreAttribute)typeAttribs[i]).MemberName); } if (!isEnum && typeAttribs[i] is ProtoPartialMemberAttribute) { if (partialMembers == null) { partialMembers = new BasicList(); } partialMembers.Add(typeAttribs[i]); } } MethodInfo[] callbacks = null; foreach (MemberInfo member in type.GetMembers(isEnum ? BindingFlags.Public | BindingFlags.Static : BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (member.DeclaringType != type) { continue; } if (member.IsDefined(typeof(ProtoIgnoreAttribute), true)) { continue; } if (partialIgnores != null && partialIgnores.Contains(member.Name)) { continue; } switch (member.MemberType) { case MemberTypes.Property: case MemberTypes.Field: ValueMember vm = ApplyDefaultBehaviour(isEnum, family, member, partialMembers); if (vm != null) { Add(vm); } break; case MemberTypes.Method: if (isEnum) { continue; } MethodInfo method = (MethodInfo)member; object[] memberAttribs = Attribute.GetCustomAttributes(method); if (memberAttribs != null && memberAttribs.Length > 0) { CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeSerializationAttribute", ref callbacks, 0); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterSerializationAttribute", ref callbacks, 1); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoBeforeDeserializationAttribute", ref callbacks, 2); CheckForCallback(method, memberAttribs, "ProtoBuf.ProtoAfterDeserializationAttribute", ref callbacks, 3); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializingAttribute", ref callbacks, 4); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnSerializedAttribute", ref callbacks, 5); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializingAttribute", ref callbacks, 6); CheckForCallback(method, memberAttribs, "System.Runtime.Serialization.OnDeserializedAttribute", ref callbacks, 7); } break; } } if (callbacks != null) { SetCallbacks(callbacks[0] ?? callbacks[4], callbacks[1] ?? callbacks[5], callbacks[2] ?? callbacks[6], callbacks[3] ?? callbacks[7]); } }
internal static Type GetListItemType(Type listType) { Helpers.DebugAssert(listType != null); if (listType == typeof(string) || listType.IsArray || !typeof(IEnumerable).IsAssignableFrom(listType)) { return(null); } BasicList candidates = new BasicList(); candidates.Add(typeof(object)); foreach (MethodInfo method in listType.GetMethods(BindingFlags.Public | BindingFlags.Instance)) { if (method.Name != "Add") { continue; } ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 1 && !candidates.Contains(parameters[0].ParameterType)) { candidates.Add(parameters[0].ParameterType); } } foreach (Type iType in listType.GetInterfaces()) { if (iType.IsGenericType && iType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.ICollection <>)) { Type[] iTypeArgs = iType.GetGenericArguments(); if (!candidates.Contains(iTypeArgs[0])) { candidates.Add(iTypeArgs[0]); } } } // more convenient GetProperty overload not supported on all platforms foreach (PropertyInfo indexer in listType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { if (indexer.Name != "Item" || candidates.Contains(indexer.PropertyType)) { continue; } ParameterInfo[] args = indexer.GetIndexParameters(); if (args.Length != 1 || args[0].ParameterType != typeof(int)) { continue; } candidates.Add(indexer.PropertyType); } switch (candidates.Count) { case 1: return(null); case 2: return((Type)candidates[1]); case 3: if (CheckDictionaryAccessors((Type)candidates[1], (Type)candidates[2])) { return((Type)candidates[1]); } if (CheckDictionaryAccessors((Type)candidates[2], (Type)candidates[1])) { return((Type)candidates[2]); } break; } return(null); }
private ValueMember ApplyDefaultBehaviour(bool isEnum, AttributeFamily family, MemberInfo member, BasicList partialMembers) { if (member == null || (family == AttributeFamily.None && !isEnum)) { return(null); // nix } Type effectiveType; switch (member.MemberType) { case MemberTypes.Field: effectiveType = ((FieldInfo)member).FieldType; break; case MemberTypes.Property: effectiveType = ((PropertyInfo)member).PropertyType; break; default: return(null); // nothing doing } int fieldNumber = 0; bool isPacked = false; string name = null; bool isRequired = false; Type itemType = null; Type defaultType = null; ResolveListTypes(effectiveType, ref itemType, ref defaultType); object[] attribs = member.GetCustomAttributes(true); Attribute attrib; DataFormat dataFormat = DataFormat.Default; bool ignore = false; object defaultValue = null; // implicit zero default switch (Type.GetTypeCode(effectiveType)) { case TypeCode.Boolean: defaultValue = false; break; case TypeCode.Decimal: defaultValue = (decimal)0; break; case TypeCode.Single: defaultValue = (float)0; break; case TypeCode.Double: defaultValue = (double)0; break; case TypeCode.Byte: defaultValue = (byte)0; break; case TypeCode.Char: defaultValue = (char)0; break; case TypeCode.Int16: defaultValue = (short)0; break; case TypeCode.Int32: defaultValue = (int)0; break; case TypeCode.Int64: defaultValue = (long)0; break; case TypeCode.SByte: defaultValue = (sbyte)0; break; case TypeCode.UInt16: defaultValue = (ushort)0; break; case TypeCode.UInt32: defaultValue = (uint)0; break; case TypeCode.UInt64: defaultValue = (ulong)0; break; default: if (effectiveType == typeof(TimeSpan)) { defaultValue = TimeSpan.Zero; } if (effectiveType == typeof(Guid)) { defaultValue = Guid.Empty; } break; } bool done = false; if (isEnum) { attrib = GetAttribute(attribs, "ProtoBuf.ProtoIgnoreAttribute"); if (attrib != null) { ignore = true; } else { attrib = GetAttribute(attribs, "ProtoBuf.ProtoEnumAttribute"); fieldNumber = Convert.ToInt32(((FieldInfo)member).GetValue(null)); if (attrib != null) { GetFieldName(ref name, attrib, "Name"); if ((bool)attrib.GetType().GetMethod("HasValue").Invoke(attrib, null)) { fieldNumber = (int)GetMemberValue(attrib, "Value"); } } } done = true; } if (!ignore && !done) // always consider ProtoMember { attrib = GetAttribute(attribs, "ProtoBuf.ProtoMemberAttribute"); GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.ProtoIgnoreAttribute"); if (!ignore) { GetFieldNumber(ref fieldNumber, attrib, "Tag"); GetFieldName(ref name, attrib, "Name"); GetFieldBoolean(ref isRequired, attrib, "IsRequired"); GetFieldBoolean(ref isPacked, attrib, "IsPacked"); GetDataFormat(ref dataFormat, attrib, "DataFormat"); done = fieldNumber > 0; } if (!done && partialMembers != null) { foreach (ProtoPartialMemberAttribute ppma in partialMembers) { if (ppma.MemberName == member.Name) { GetFieldNumber(ref fieldNumber, ppma, "Tag"); GetFieldName(ref name, ppma, "Name"); GetFieldBoolean(ref isRequired, ppma, "IsRequired"); GetFieldBoolean(ref isPacked, ppma, "IsPacked"); GetDataFormat(ref dataFormat, ppma, "DataFormat"); if (done = fieldNumber > 0) { break; } } } } } if (!ignore && !done && HasFamily(family, AttributeFamily.DataContractSerialier)) { attrib = GetAttribute(attribs, "System.Runtime.Serialization.DataMemberAttribute"); GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "Name"); GetFieldBoolean(ref isRequired, attrib, "IsRequired"); done = fieldNumber > 0; } if (!ignore && !done && HasFamily(family, AttributeFamily.XmlSerializer)) { attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlElementAttribute"); GetIgnore(ref ignore, attrib, attribs, "System.Xml.Serialization.XmlIgnoreAttribute"); if (!ignore) { GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "ElementName"); } attrib = GetAttribute(attribs, "System.Xml.Serialization.XmlArrayAttribute"); GetIgnore(ref ignore, attrib, attribs, "ProtoBuf.XmlIgnoreAttribute"); if (!ignore) { GetFieldNumber(ref fieldNumber, attrib, "Order"); GetFieldName(ref name, attrib, "ElementName"); } done = fieldNumber > 0; } if (!ignore && (attrib = GetAttribute(attribs, "System.ComponentModel.DefaultValueAttribute")) != null) { defaultValue = GetMemberValue(attrib, "Value"); } ValueMember vm = ((isEnum || fieldNumber > 0) && !ignore) ? new ValueMember(model, type, fieldNumber, member, effectiveType, itemType, defaultType, dataFormat, defaultValue) : null; if (vm != null) { PropertyInfo prop = type.GetProperty(member.Name + "Specified", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, typeof(bool), Helpers.EmptyTypes, null); if (prop != null) { vm.SetSpecified(prop.GetGetMethod(true), prop.GetSetMethod(true)); } else { MethodInfo method = type.GetMethod("ShouldSerialize" + member.Name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Helpers.EmptyTypes, null); if (method != null && method.ReturnType == typeof(bool)) { vm.SetSpecified(method, null); } } if (!Helpers.IsNullOrEmpty(name)) { vm.SetName(name); } vm.IsPacked = isPacked; vm.IsRequired = isRequired; } return(vm); }
/// <summary> /// Fully compiles the current model into a static-compiled serialization dll /// (the serialization dll still requires protobuf-net for support services). /// </summary> /// <remarks>A full compilation is restricted to accessing public types / members</remarks> /// <param name="name">The name of the TypeModel class to create</param> /// <param name="path">The path for the new dll</param> /// <returns>An instance of the newly created compiled type-model</returns> public TypeModel Compile(string name, string path) { BuildAllSerializers(); Freeze(); bool save = !Helpers.IsNullOrEmpty(path); if (Helpers.IsNullOrEmpty(name)) { if (save) { throw new ArgumentNullException("name"); } name = Guid.NewGuid().ToString(); } AssemblyName an = new AssemblyName(); an.Name = name; AssemblyBuilder asm = AppDomain.CurrentDomain.DefineDynamicAssembly(an, (save ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run) ); ModuleBuilder module = save ? asm.DefineDynamicModule(name, path) : asm.DefineDynamicModule(name); Type baseType = typeof(TypeModel); TypeBuilder type = module.DefineType(name, (baseType.Attributes & ~TypeAttributes.Abstract) | TypeAttributes.Sealed, baseType); Compiler.CompilerContext ctx; int index = 0; bool hasInheritance = false; SerializerPair[] methodPairs = new SerializerPair[types.Count]; foreach (MetaType metaType in types) { MethodBuilder writeMethod = type.DefineMethod("Write", MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard, typeof(void), new Type[] { metaType.Type, typeof(ProtoWriter) }); MethodBuilder readMethod = type.DefineMethod("Read", MethodAttributes.Private | MethodAttributes.Static, CallingConventions.Standard, metaType.Type, new Type[] { metaType.Type, typeof(ProtoReader) }); SerializerPair pair = new SerializerPair( GetKey(metaType.Type, true, false), GetKey(metaType.Type, true, true), metaType, writeMethod, readMethod, writeMethod.GetILGenerator(), readMethod.GetILGenerator()); methodPairs[index++] = pair; if (pair.MetaKey != pair.BaseKey) { hasInheritance = true; } } if (hasInheritance) { Array.Sort(methodPairs); } for (index = 0; index < methodPairs.Length; index++) { SerializerPair pair = methodPairs[index]; ctx = new Compiler.CompilerContext(pair.SerializeBody, true, methodPairs); pair.Type.Serializer.EmitWrite(ctx, Compiler.Local.InputValue); ctx.Return(); ctx = new Compiler.CompilerContext(pair.DeserializeBody, true, methodPairs); pair.Type.Serializer.EmitRead(ctx, Compiler.Local.InputValue); ctx.LoadValue(Compiler.Local.InputValue); ctx.Return(); } FieldBuilder knownTypes = type.DefineField("knownTypes", typeof(Type[]), FieldAttributes.Private | FieldAttributes.InitOnly); ILGenerator il = Override(type, "GetKeyImpl"); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, knownTypes); il.Emit(OpCodes.Ldarg_1); // note that Array.IndexOf is not supported under CF il.EmitCall(OpCodes.Callvirt, typeof(IList).GetMethod( "IndexOf", new Type[] { typeof(object) }), null); if (hasInheritance) { il.DeclareLocal(typeof(int)); // loc-0 il.Emit(OpCodes.Dup); il.Emit(OpCodes.Stloc_0); BasicList getKeyLabels = new BasicList(); int lastKey = -1; for (int i = 0; i < methodPairs.Length; i++) { if (methodPairs[i].MetaKey == methodPairs[i].BaseKey) { break; } if (lastKey == methodPairs[i].BaseKey) { // add the last label again getKeyLabels.Add(getKeyLabels[getKeyLabels.Count - 1]); } else { // add a new unique label getKeyLabels.Add(il.DefineLabel()); lastKey = methodPairs[i].BaseKey; } } Label[] subtypeLabels = new Label[getKeyLabels.Count]; getKeyLabels.CopyTo(subtypeLabels, 0); il.Emit(OpCodes.Switch, subtypeLabels); il.Emit(OpCodes.Ldloc_0); // not a sub-type; use the original value il.Emit(OpCodes.Ret); lastKey = -1; // now output the different branches per sub-type (not derived type) for (int i = subtypeLabels.Length - 1; i >= 0; i--) { if (lastKey != methodPairs[i].BaseKey) { lastKey = methodPairs[i].BaseKey; // find the actual base-index for this base-key (i.e. the index of // the base-type) int keyIndex = -1; for (int j = subtypeLabels.Length; j < methodPairs.Length; j++) { if (methodPairs[j].BaseKey == lastKey && methodPairs[j].MetaKey == lastKey) { keyIndex = j; break; } } il.MarkLabel(subtypeLabels[i]); Compiler.CompilerContext.LoadValue(il, keyIndex); il.Emit(OpCodes.Ret); } } } else { il.Emit(OpCodes.Ret); } il = Override(type, "Serialize"); ctx = new Compiler.CompilerContext(il, false, methodPairs); // arg0 = this, arg1 = key, arg2=obj, arg3=dest Label[] jumpTable = new Label[types.Count]; for (int i = 0; i < jumpTable.Length; i++) { jumpTable[i] = il.DefineLabel(); } il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Switch, jumpTable); ctx.Return(); for (int i = 0; i < jumpTable.Length; i++) { SerializerPair pair = methodPairs[i]; il.MarkLabel(jumpTable[i]); il.Emit(OpCodes.Ldarg_2); ctx.CastFromObject(pair.Type.Type); il.Emit(OpCodes.Ldarg_3); il.EmitCall(OpCodes.Call, pair.Serialize, null); ctx.Return(); } il = Override(type, "Deserialize"); ctx = new Compiler.CompilerContext(il, false, methodPairs); // arg0 = this, arg1 = key, arg2=obj, arg3=source for (int i = 0; i < jumpTable.Length; i++) { jumpTable[i] = il.DefineLabel(); } il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Switch, jumpTable); ctx.LoadNullRef(); ctx.Return(); for (int i = 0; i < jumpTable.Length; i++) { SerializerPair pair = methodPairs[i]; il.MarkLabel(jumpTable[i]); Type keyType = pair.Type.Type; if (keyType.IsValueType) { il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.EmitCall(OpCodes.Call, EmitBoxedSerializer(type, i, keyType, methodPairs), null); ctx.Return(); } else { il.Emit(OpCodes.Ldarg_2); ctx.CastFromObject(keyType); il.Emit(OpCodes.Ldarg_3); il.EmitCall(OpCodes.Call, pair.Deserialize, null); ctx.Return(); } } ConstructorBuilder ctor = type.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Helpers.EmptyTypes); il = ctor.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, baseType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0]); il.Emit(OpCodes.Ldarg_0); Compiler.CompilerContext.LoadValue(il, types.Count); il.Emit(OpCodes.Newarr, typeof(Type)); index = 0; foreach (SerializerPair pair in methodPairs) { il.Emit(OpCodes.Dup); Compiler.CompilerContext.LoadValue(il, index); il.Emit(OpCodes.Ldtoken, pair.Type.Type); il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); il.Emit(OpCodes.Stelem_Ref); index++; } il.Emit(OpCodes.Stfld, knownTypes); il.Emit(OpCodes.Ret); Type finalType = type.CreateType(); if (!Helpers.IsNullOrEmpty(path)) { asm.Save(path); Helpers.DebugWriteLine("Wrote dll:" + path); } return((TypeModel)Activator.CreateInstance(finalType)); }