private OneofAccessor CreateAccessor(string clrName) { // We won't have a CLR name if this is from a dynamically-loaded FileDescriptor. // TODO: Support dynamic messages. if (clrName == null) { return(null); } if (IsSynthetic) { return(OneofAccessor.ForSyntheticOneof(this)); } else { var caseProperty = containingType.ClrType.GetProperty(clrName + "Case"); if (caseProperty == null) { throw new DescriptorValidationException(this, $"Property {clrName}Case not found in {containingType.ClrType}"); } if (!caseProperty.CanRead) { throw new ArgumentException($"Cannot read from property {clrName}Case in {containingType.ClrType}"); } var clearMethod = containingType.ClrType.GetMethod("Clear" + clrName); if (clearMethod == null) { throw new DescriptorValidationException(this, $"Method Clear{clrName} not found in {containingType.ClrType}"); } return(OneofAccessor.ForRegularOneof(this, caseProperty, clearMethod)); } }
internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, string clrName) : base(file, file.ComputeFullName(parent, proto.Name), index) { this.proto = proto; containingType = parent; file.DescriptorPool.AddSymbol(this); // It's useful to determine whether or not this is a synthetic oneof before cross-linking. That means // diving into the proto directly rather than using FieldDescriptor, but that's okay. var firstFieldInOneof = parent.Proto.Field.FirstOrDefault(fieldProto => fieldProto.HasOneofIndex && fieldProto.OneofIndex == index); IsSynthetic = firstFieldInOneof?.Proto3Optional ?? false; accessor = CreateAccessor(clrName); }