internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor) { if (!property.CanWrite) { throw new ArgumentException("Not all required properties/methods available"); } setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod()); if (descriptor.File.Proto.Syntax == "proto2") { MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod; hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod ?? throw new ArgumentException("Not all required properties/methods are available")); MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes); clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod ?? throw new ArgumentException("Not all required properties/methods are available")); } else { hasDelegate = (_) => throw new InvalidOperationException("HasValue is not implemented for proto3 fields"); var clrType = property.PropertyType; // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.) object defaultValue = descriptor.FieldType == FieldType.Message ? null : clrType == typeof(string) ? "" : clrType == typeof(ByteString) ? ByteString.Empty : Activator.CreateInstance(clrType); clearDelegate = message => SetValue(message, defaultValue); } }
internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor) { while (true) { IL_10F: uint arg_E3_0 = 1941025569u; while (true) { uint num; switch ((num = (arg_E3_0 ^ 199827664u)) % 8u) { case 1u: arg_E3_0 = (num * 3210510662u ^ 4032699640u); continue; case 2u: goto IL_10F; case 3u: goto IL_116; case 4u: { Type type; __c__DisplayClass2_.defaultValue = ((descriptor.FieldType == FieldType.Message) ? null : ((type == SingleFieldAccessor.smethod_3(typeof(string).TypeHandle)) ? "" : ((type == SingleFieldAccessor.smethod_3(typeof(ByteString).TypeHandle)) ? ByteString.Empty : SingleFieldAccessor.smethod_4(type)))); this.clearDelegate = delegate(IMessage message) { __c__DisplayClass2_.__4__this.SetValue(message, __c__DisplayClass2_.defaultValue); }; arg_E3_0 = 1884219440u; continue; } case 5u: this.setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod()); arg_E3_0 = 2064311039u; continue; case 6u: __c__DisplayClass2_.__4__this = this; arg_E3_0 = ((SingleFieldAccessor.smethod_0(property) ? 2142081437u : 1483086867u) ^ num * 2346426732u); continue; case 7u: { Type type = SingleFieldAccessor.smethod_2(property); arg_E3_0 = (num * 1124000945u ^ 3750043923u); continue; } } goto Block_5; } } Block_5: return; IL_116: throw SingleFieldAccessor.smethod_1(Module.smethod_35 <string>(1200568613u)); }
internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor) { if (!property.CanWrite) { throw new ArgumentException("Not all required properties/methods available"); } setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod()); if (descriptor.File.Syntax == Syntax.Proto3 && !descriptor.Proto.Proto3Optional) { hasDelegate = message => { throw new InvalidOperationException("HasValue is not implemented for non-optional proto3 fields"); }; var clrType = property.PropertyType; // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.) object defaultValue = descriptor.FieldType == FieldType.Message ? null : clrType == typeof(string) ? "" : clrType == typeof(ByteString) ? ByteString.Empty : Activator.CreateInstance(clrType); clearDelegate = message => SetValue(message, defaultValue); } else { // For message fields, just compare with null and set to null. // For primitive fields, use the Has/Clear methods. if (descriptor.FieldType == FieldType.Message) { hasDelegate = message => GetValue(message) != null; clearDelegate = message => SetValue(message, null); } else { MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod; if (hasMethod == null) { throw new ArgumentException("Not all required properties/methods are available"); } hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod); MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes); if (clearMethod == null) { throw new ArgumentException("Not all required properties/methods are available"); } clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod); } } }
internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor) { if (!property.CanWrite) { throw new ArgumentException("Not all required properties/methods available"); } setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod()); var clrType = property.PropertyType; // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.) object defaultValue = typeof(IMessage).IsAssignableFrom(clrType) ? null : clrType == typeof(string) ? "" : clrType == typeof(ByteString) ? ByteString.Empty : Activator.CreateInstance(clrType); clearDelegate = message => SetValue(message, defaultValue); }
internal SingleFieldAccessor(PropertyInfo property, FieldDescriptor descriptor) : base(property, descriptor) { if (!property.CanWrite) { throw new ArgumentException("Not all required properties/methods available"); } setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod()); // Note: this looks worrying in that we access the containing oneof, which isn't valid until cross-linking // is complete... but field accessors aren't created until after cross-linking. // The oneof itself won't be cross-linked yet, but that's okay: the oneof accessor is created // earlier. // Message fields always support presence, via null checks. if (descriptor.FieldType == FieldType.Message) { hasDelegate = message => GetValue(message) != null; clearDelegate = message => SetValue(message, null); } // Oneof fields always support presence, via case checks. // Note that clearing the field is a no-op unless that specific field is the current "case". else if (descriptor.RealContainingOneof != null) { var oneofAccessor = descriptor.RealContainingOneof.Accessor; hasDelegate = message => oneofAccessor.GetCaseFieldDescriptor(message) == descriptor; clearDelegate = message => { // Clear on a field only affects the oneof itself if the current case is the field we're accessing. if (oneofAccessor.GetCaseFieldDescriptor(message) == descriptor) { oneofAccessor.Clear(message); } }; } // Primitive fields always support presence in proto2, and support presence in proto3 for optional fields. else if (descriptor.File.Syntax == Syntax.Proto2 || descriptor.Proto.Proto3Optional) { MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod; if (hasMethod == null) { throw new ArgumentException("Not all required properties/methods are available"); } hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod); MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes); if (clearMethod == null) { throw new ArgumentException("Not all required properties/methods are available"); } clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod); } // What's left? // Primitive proto3 fields without the optional keyword, which aren't in oneofs. else { hasDelegate = message => { throw new InvalidOperationException("Presence is not implemented for this field"); }; // While presence isn't supported, clearing still is; it's just setting to a default value. var clrType = property.PropertyType; if (clrType is ILRuntimeWrapperType wrapperType) { clrType = wrapperType.RealType; } object defaultValue = clrType == typeof(string) ? "" : clrType == typeof(ByteString) ? ByteString.Empty : (clrType is ILRuntimeType) ? (clrType as ILRuntimeType).ILType.Instantiate() : Activator.CreateInstance(clrType); clearDelegate = message => SetValue(message, defaultValue); } }