internal static ListDecorator Create(TypeModel model, Type declaredType, Type concreteType, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, bool returnList, bool overwriteList, bool supportNull) { if (returnList && ImmutableCollectionDecorator.IdentifyImmutable(model, declaredType, out MethodInfo builderFactory, out MethodInfo methodInfo, out MethodInfo addRange, out MethodInfo finish)) { return(new ImmutableCollectionDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull, builderFactory, methodInfo, addRange, finish)); } return(new ListDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull)); }
internal static ListDecorator Create(TypeModel model, Type declaredType, Type concreteType, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, bool returnList, bool overwriteList, bool supportNull, bool dontThrowNullReference) { #if !NO_GENERICS MethodInfo builderFactory, add, addRange, finish; if (returnList && ImmutableCollectionDecorator.IdentifyImmutable(model, declaredType, out builderFactory, out add, out addRange, out finish)) { return(new ImmutableCollectionDecorator( model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull, dontThrowNullReference, builderFactory, add, addRange, finish)); } #endif return(new ListDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull, dontThrowNullReference)); }
internal static ListDecorator Create(TypeModel model, Type declaredType, Type concreteType, IProtoSerializer tail, int fieldNumber, bool writePacked, WireType packedWireType, bool returnList, bool overwriteList, bool supportNull) { MethodInfo methodInfo; MethodInfo methodInfo1; MethodInfo methodInfo2; MethodInfo methodInfo3; if (!returnList || !ImmutableCollectionDecorator.IdentifyImmutable(model, declaredType, out methodInfo, out methodInfo1, out methodInfo2, out methodInfo3)) { return(new ListDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull)); } return(new ImmutableCollectionDecorator(model, declaredType, concreteType, tail, fieldNumber, writePacked, packedWireType, returnList, overwriteList, supportNull, methodInfo, methodInfo1, methodInfo2, methodInfo3)); }
// Token: 0x06003574 RID: 13684 RVA: 0x001345BC File Offset: 0x001329BC internal static bool IdentifyImmutable(TypeModel model, Type declaredType, out MethodInfo builderFactory, out MethodInfo add, out MethodInfo addRange, out MethodInfo finish) { MethodInfo methodInfo; finish = methodInfo = null; addRange = methodInfo; add = methodInfo; builderFactory = methodInfo; if (model == null || declaredType == null) { return(false); } if (!declaredType.IsGenericType) { return(false); } Type[] genericArguments = declaredType.GetGenericArguments(); int num = genericArguments.Length; Type[] array; if (num != 1) { if (num != 2) { return(false); } Type type = model.MapType(typeof(KeyValuePair <, >)); if (type == null) { return(false); } type = type.MakeGenericType(genericArguments); array = new Type[] { type }; } else { array = genericArguments; } if (ImmutableCollectionDecorator.ResolveIReadOnlyCollection(declaredType, null) == null) { return(false); } string text = declaredType.Name; int num2 = text.IndexOf('`'); if (num2 <= 0) { return(false); } text = ((!declaredType.IsInterface) ? text.Substring(0, num2) : text.Substring(1, num2 - 1)); Type type2 = model.GetType(declaredType.Namespace + "." + text, declaredType.Assembly); if (type2 == null && text == "ImmutableSet") { type2 = model.GetType(declaredType.Namespace + ".ImmutableHashSet", declaredType.Assembly); } if (type2 == null) { return(false); } foreach (MethodInfo methodInfo2 in type2.GetMethods()) { if (methodInfo2.IsStatic && !(methodInfo2.Name != "CreateBuilder") && methodInfo2.IsGenericMethodDefinition && methodInfo2.GetParameters().Length == 0 && methodInfo2.GetGenericArguments().Length == genericArguments.Length) { builderFactory = methodInfo2.MakeGenericMethod(genericArguments); break; } } Type type3 = model.MapType(typeof(void)); if (builderFactory == null || builderFactory.ReturnType == null || builderFactory.ReturnType == type3) { return(false); } add = Helpers.GetInstanceMethod(builderFactory.ReturnType, "Add", array); if (add == null) { return(false); } finish = Helpers.GetInstanceMethod(builderFactory.ReturnType, "ToImmutable", Helpers.EmptyTypes); if (finish == null || finish.ReturnType == null || finish.ReturnType == type3) { return(false); } if (finish.ReturnType != declaredType && !Helpers.IsAssignableFrom(declaredType, finish.ReturnType)) { return(false); } addRange = Helpers.GetInstanceMethod(builderFactory.ReturnType, "AddRange", new Type[] { declaredType }); if (addRange == null) { Type type4 = model.MapType(typeof(IEnumerable <>), false); if (type4 != null) { addRange = Helpers.GetInstanceMethod(builderFactory.ReturnType, "AddRange", new Type[] { type4.MakeGenericType(array) }); } } return(true); }
protected override void EmitRead(CompilerContext ctx, Local valueFrom) { MethodInfo methodInfo; MethodInfo methodInfo1; Local localWithValue; if (base.AppendToCollection) { localWithValue = ctx.GetLocalWithValue(this.ExpectedType, valueFrom); } else { localWithValue = null; } using (Local local = localWithValue) { using (Local local1 = new Local(ctx, this.builderFactory.ReturnType)) { ctx.EmitCall(this.builderFactory); ctx.StoreValue(local1); if (base.AppendToCollection) { CodeLabel codeLabel = ctx.DefineLabel(); if (!this.ExpectedType.IsValueType) { ctx.LoadValue(local); ctx.BranchIfFalse(codeLabel, false); } PropertyInfo property = Helpers.GetProperty(this.ExpectedType, "Length", false) ?? Helpers.GetProperty(this.ExpectedType, "Count", false) ?? Helpers.GetProperty(ImmutableCollectionDecorator.ResolveIReadOnlyCollection(this.ExpectedType, this.Tail.ExpectedType), "Count", false); ctx.LoadAddress(local, local.Type); ctx.EmitCall(Helpers.GetGetMethod(property, false, false)); ctx.BranchIfFalse(codeLabel, false); Type type = ctx.MapType(typeof(void)); if (this.addRange == null) { MethodInfo enumeratorInfo = base.GetEnumeratorInfo(ctx.Model, out methodInfo, out methodInfo1); Type returnType = enumeratorInfo.ReturnType; using (Local local2 = new Local(ctx, returnType)) { ctx.LoadAddress(local, this.ExpectedType); ctx.EmitCall(enumeratorInfo); ctx.StoreValue(local2); using (IDisposable disposable = ctx.Using(local2)) { CodeLabel codeLabel1 = ctx.DefineLabel(); CodeLabel codeLabel2 = ctx.DefineLabel(); ctx.Branch(codeLabel2, false); ctx.MarkLabel(codeLabel1); ctx.LoadAddress(local1, local1.Type); ctx.LoadAddress(local2, returnType); ctx.EmitCall(methodInfo1); ctx.EmitCall(this.@add); if ([email protected] != null && [email protected] != type) { ctx.DiscardValue(); } ctx.MarkLabel(codeLabel2); ctx.LoadAddress(local2, returnType); ctx.EmitCall(methodInfo); ctx.BranchIfTrue(codeLabel1, false); } } } else { ctx.LoadValue(local1); ctx.LoadValue(local); ctx.EmitCall(this.addRange); if (this.addRange.ReturnType != null && [email protected] != type) { ctx.DiscardValue(); } } ctx.MarkLabel(codeLabel); } ListDecorator.EmitReadList(ctx, local1, this.Tail, this.@add, this.packedWireType, false); ctx.LoadAddress(local1, local1.Type); ctx.EmitCall(this.finish); if (this.ExpectedType != this.finish.ReturnType) { ctx.Cast(this.ExpectedType); } } } }
internal static bool IdentifyImmutable(TypeModel model, Type declaredType, out MethodInfo builderFactory, out MethodInfo add, out MethodInfo addRange, out MethodInfo finish) { Type[] typeArray; object obj = null; MethodInfo methodInfo = (MethodInfo)obj; finish = (MethodInfo)obj; MethodInfo methodInfo1 = methodInfo; MethodInfo methodInfo2 = methodInfo1; addRange = methodInfo1; MethodInfo methodInfo3 = methodInfo2; MethodInfo methodInfo4 = methodInfo3; add = methodInfo3; builderFactory = methodInfo4; if (model == null || declaredType == null) { return(false); } Type type = declaredType; if (!type.IsGenericType) { return(false); } Type[] genericArguments = type.GetGenericArguments(); switch ((int)genericArguments.Length) { case 1: { typeArray = genericArguments; break; } case 2: { Type type1 = model.MapType(typeof(KeyValuePair <,>)); if (type1 == null) { return(false); } type1 = type1.MakeGenericType(genericArguments); typeArray = new Type[] { type1 }; break; } default: { return(false); } } if (ImmutableCollectionDecorator.ResolveIReadOnlyCollection(declaredType, null) == null) { return(false); } string name = declaredType.Name; int num = name.IndexOf('\u0060'); if (num <= 0) { return(false); } name = (type.IsInterface ? name.Substring(1, num - 1) : name.Substring(0, num)); Type type2 = model.GetType(string.Concat(declaredType.Namespace, ".", name), type.Assembly); if (type2 == null && name == "ImmutableSet") { type2 = model.GetType(string.Concat(declaredType.Namespace, ".ImmutableHashSet"), type.Assembly); } if (type2 == null) { return(false); } MethodInfo[] methods = type2.GetMethods(); int num1 = 0; while (num1 < (int)methods.Length) { MethodInfo methodInfo5 = methods[num1]; if (!methodInfo5.IsStatic || methodInfo5.Name != "CreateBuilder" || !methodInfo5.IsGenericMethodDefinition || (int)methodInfo5.GetParameters().Length != 0 || (int)methodInfo5.GetGenericArguments().Length != (int)genericArguments.Length) { num1++; } else { builderFactory = methodInfo5.MakeGenericMethod(genericArguments); break; } } Type type3 = model.MapType(typeof(void)); if (builderFactory == null || builderFactory.ReturnType == null || builderFactory.ReturnType == type3) { return(false); } add = Helpers.GetInstanceMethod(builderFactory.ReturnType, "Add", typeArray); if (add == null) { return(false); } finish = Helpers.GetInstanceMethod(builderFactory.ReturnType, "ToImmutable", Helpers.EmptyTypes); if (finish == null || finish.ReturnType == null || finish.ReturnType == type3) { return(false); } if (finish.ReturnType != declaredType && !Helpers.IsAssignableFrom(declaredType, finish.ReturnType)) { return(false); } Type returnType = builderFactory.ReturnType; Type[] typeArray1 = new Type[] { declaredType }; addRange = Helpers.GetInstanceMethod(returnType, "AddRange", typeArray1); if (addRange == null) { Type type4 = model.MapType(typeof(IEnumerable <>), false); if (type4 != null) { Type returnType1 = builderFactory.ReturnType; Type[] typeArray2 = new Type[] { type4.MakeGenericType(typeArray) }; addRange = Helpers.GetInstanceMethod(returnType1, "AddRange", typeArray2); } } return(true); }