| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| using System; |
| using System.Reflection; |
| using System.Collections; |
| |
| namespace Avro.Reflect |
| { |
| internal class DotnetProperty |
| { |
| private PropertyInfo _property; |
| |
| public IAvroFieldConverter Converter { get; set; } |
| |
| private bool IsPropertyCompatible(Avro.Schema schema) |
| { |
| Type propType; |
| var schemaTag = schema.Tag; |
| |
| if (Converter == null) |
| { |
| propType = _property.PropertyType; |
| } |
| else |
| { |
| propType = Converter.GetAvroType(); |
| } |
| |
| switch (schemaTag) |
| { |
| case Avro.Schema.Type.Null: |
| return (Nullable.GetUnderlyingType(propType) != null) || (!propType.IsValueType); |
| case Avro.Schema.Type.Boolean: |
| return propType == typeof(bool); |
| case Avro.Schema.Type.Int: |
| return propType == typeof(int); |
| case Avro.Schema.Type.Long: |
| return propType == typeof(long); |
| case Avro.Schema.Type.Float: |
| return propType == typeof(float); |
| case Avro.Schema.Type.Double: |
| return propType == typeof(double); |
| case Avro.Schema.Type.Bytes: |
| return propType == typeof(byte[]); |
| case Avro.Schema.Type.String: |
| return typeof(string).IsAssignableFrom(propType); |
| case Avro.Schema.Type.Record: |
| //TODO: this probably should work for struct too |
| return propType.IsClass; |
| case Avro.Schema.Type.Enumeration: |
| return propType.IsEnum; |
| case Avro.Schema.Type.Array: |
| return typeof(IEnumerable).IsAssignableFrom(propType); |
| case Avro.Schema.Type.Map: |
| return typeof(IDictionary).IsAssignableFrom(propType); |
| case Avro.Schema.Type.Union: |
| return true; |
| case Avro.Schema.Type.Fixed: |
| return propType == typeof(byte[]); |
| case Avro.Schema.Type.Error: |
| return propType.IsClass; |
| case Avro.Schema.Type.Logical: |
| var logicalSchema = (LogicalSchema)schema; |
| var type = logicalSchema.LogicalType.GetCSharpType(false); |
| return type == propType; |
| } |
| |
| return false; |
| } |
| |
| public DotnetProperty(PropertyInfo property, Avro.Schema schema, IAvroFieldConverter converter, ClassCache cache) |
| { |
| _property = property; |
| Converter = converter; |
| |
| if (!IsPropertyCompatible(schema)) |
| { |
| if (Converter == null) |
| { |
| var c = cache.GetDefaultConverter(schema.Tag, _property.PropertyType); |
| if (c != null) |
| { |
| Converter = c; |
| return; |
| } |
| } |
| |
| throw new AvroException($"Property {property.Name} in object {property.DeclaringType} isn't compatible with Avro schema type {schema.Tag}"); |
| } |
| } |
| |
| public DotnetProperty(PropertyInfo property, Avro.Schema schema, ClassCache cache) |
| : this(property, schema, null, cache) |
| { |
| } |
| |
| public virtual Type GetPropertyType() |
| { |
| if (Converter != null) |
| { |
| return Converter.GetAvroType(); |
| } |
| |
| return _property.PropertyType; |
| } |
| |
| public virtual object GetValue(object o, Schema s) |
| { |
| if (Converter != null) |
| { |
| return Converter.ToAvroType(_property.GetValue(o), s); |
| } |
| |
| return _property.GetValue(o); |
| } |
| |
| public virtual void SetValue(object o, object v, Schema s) |
| { |
| if (Converter != null) |
| { |
| _property.SetValue(o, Converter.FromAvroType(v, s)); |
| } |
| else |
| { |
| _property.SetValue(o, v); |
| } |
| } |
| } |
| } |