static List <PropertyConverter> GetPropertyConvertersForType(Type type) { var propertyConverters = new List <PropertyConverter>(); BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly; // Loop through the type hierarchy to find all [DataMember] attributes which belong to [DataContract] classes. while (type != null && type.GetCustomAttribute <DataContractAttribute>() != null) { foreach (MemberInfo member in type.GetMembers(flags)) { DataMemberAttribute dataMember = member.GetCustomAttribute <DataMemberAttribute>(); if (dataMember == null) { continue; } PropertyInfo property = member as PropertyInfo; FieldInfo field = member as FieldInfo; if (property == null && field == null) { throw new InvalidDataContractException("Only fields and properties can be marked as [DataMember]."); } else if (property != null && (!property.CanWrite || !property.CanRead)) { throw new InvalidDataContractException("[DataMember] properties must be both readable and writeable."); } // Timestamp is a reserved property name in Table Storage, so the name needs to be changed. string propertyName = dataMember.Name ?? member.Name; if (string.Equals(propertyName, "Timestamp", StringComparison.OrdinalIgnoreCase)) { propertyName = "_Timestamp"; } Func <object, EntityProperty> getEntityPropertyFunc; Action <object, EntityProperty> setObjectPropertyFunc; Type memberValueType = property != null ? property.PropertyType : field.FieldType; if (typeof(string).IsAssignableFrom(memberValueType)) { if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForString((string)property.GetValue(o)); setObjectPropertyFunc = (o, e) => property.SetValue(o, e.StringValue); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForString((string)field.GetValue(o)); setObjectPropertyFunc = (o, e) => field.SetValue(o, e.StringValue); } } else if (memberValueType.IsEnum) { // Enums are serialized as strings for readability. if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForString(property.GetValue(o).ToString()); setObjectPropertyFunc = (o, e) => property.SetValue(o, Enum.Parse(memberValueType, e.StringValue)); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForString(field.GetValue(o).ToString()); setObjectPropertyFunc = (o, e) => field.SetValue(o, Enum.Parse(memberValueType, e.StringValue)); } } else if (typeof(int?).IsAssignableFrom(memberValueType)) { if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForInt((int)property.GetValue(o)); setObjectPropertyFunc = (o, e) => property.SetValue(o, e.Int32Value); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForInt((int)field.GetValue(o)); setObjectPropertyFunc = (o, e) => field.SetValue(o, e.Int32Value); } } else if (typeof(long?).IsAssignableFrom(memberValueType)) { if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForLong((long)property.GetValue(o)); setObjectPropertyFunc = (o, e) => property.SetValue(o, e.Int64Value); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForLong((long)field.GetValue(o)); setObjectPropertyFunc = (o, e) => field.SetValue(o, e.Int64Value); } } else if (typeof(bool?).IsAssignableFrom(memberValueType)) { if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForBool((bool)property.GetValue(o)); setObjectPropertyFunc = (o, e) => property.SetValue(o, e.BooleanValue); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForBool((bool)field.GetValue(o)); setObjectPropertyFunc = (o, e) => field.SetValue(o, e.BooleanValue); } } else if (typeof(DateTime?).IsAssignableFrom(memberValueType)) { if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForDateTimeOffset((DateTime?)property.GetValue(o)); setObjectPropertyFunc = (o, e) => property.SetValue(o, e.DateTime); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForDateTimeOffset((DateTime?)field.GetValue(o)); setObjectPropertyFunc = (o, e) => field.SetValue(o, e.DateTime); } } else if (typeof(DateTimeOffset?).IsAssignableFrom(memberValueType)) { if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForDateTimeOffset((DateTimeOffset?)property.GetValue(o)); setObjectPropertyFunc = (o, e) => property.SetValue(o, e.DateTimeOffsetValue); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForDateTimeOffset((DateTimeOffset?)field.GetValue(o)); setObjectPropertyFunc = (o, e) => field.SetValue(o, e.DateTimeOffsetValue); } } else if (typeof(Guid?).IsAssignableFrom(memberValueType)) { if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForGuid((Guid?)property.GetValue(o)); setObjectPropertyFunc = (o, e) => property.SetValue(o, e.GuidValue); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForGuid((Guid?)field.GetValue(o)); setObjectPropertyFunc = (o, e) => field.SetValue(o, e.GuidValue); } } else if (typeof(double?).IsAssignableFrom(memberValueType)) { if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForDouble((double?)property.GetValue(o)); setObjectPropertyFunc = (o, e) => property.SetValue(o, e.DoubleValue); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForDouble((double?)field.GetValue(o)); setObjectPropertyFunc = (o, e) => field.SetValue(o, e.DoubleValue); } } else if (typeof(byte[]).IsAssignableFrom(memberValueType)) { if (property != null) { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForByteArray((byte[])property.GetValue(o)); setObjectPropertyFunc = (o, e) => property.SetValue(o, e.BinaryValue); } else { getEntityPropertyFunc = o => EntityProperty.GeneratePropertyForByteArray((byte[])field.GetValue(o)); setObjectPropertyFunc = (o, e) => field.SetValue(o, e.BinaryValue); } } else // assume a serializeable object { getEntityPropertyFunc = o => { object value = property != null?property.GetValue(o) : field.GetValue(o); string json = value != null?JsonConvert.SerializeObject(value) : null; return(EntityProperty.GeneratePropertyForString(json)); }; setObjectPropertyFunc = (o, e) => { string json = e.StringValue; object value = json != null?JsonConvert.DeserializeObject(json, memberValueType) : null; if (property != null) { property.SetValue(o, value); } else { field.SetValue(o, value); } }; } propertyConverters.Add(new PropertyConverter(propertyName, getEntityPropertyFunc, setObjectPropertyFunc)); } type = type.BaseType; } return(propertyConverters); }
public override IDictionary <string, EntityProperty> WriteEntity(OperationContext operationContext) { var properties = new Dictionary <string, EntityProperty>(); foreach (var getter in Getters) { var value = getter.Value.Item2(Entity); if (value == null) { continue; } var type = getter.Value.Item1; EntityProperty entityProperty = null; if (type == typeof(bool) || type == typeof(bool?)) { entityProperty = EntityProperty.GeneratePropertyForBool((bool?)value); } else if (type == typeof(int) || type == typeof(int?)) { entityProperty = EntityProperty.GeneratePropertyForInt((int?)value); } else if (type == typeof(long) || type == typeof(long?)) { entityProperty = EntityProperty.GeneratePropertyForLong((long?)value); } else if (type == typeof(double) || type == typeof(double?)) { entityProperty = EntityProperty.GeneratePropertyForDouble((double?)value); } else if (type == typeof(float) || type == typeof(float?)) { entityProperty = EntityProperty.GeneratePropertyForDouble((float?)value); } else if (type == typeof(DateTime) || type == typeof(DateTime?)) { entityProperty = EntityProperty.GeneratePropertyForDateTimeOffset((DateTime?)value); } else if (type == typeof(DateTimeOffset) || type == typeof(DateTimeOffset?)) { entityProperty = EntityProperty.GeneratePropertyForDateTimeOffset((DateTimeOffset?)value); } else if (type == typeof(Guid) || type == typeof(Guid?)) { entityProperty = EntityProperty.GeneratePropertyForGuid((Guid?)value); } else if (type == typeof(byte[])) { entityProperty = EntityProperty.GeneratePropertyForByteArray(value as byte[]); } else if (type == typeof(string)) { entityProperty = EntityProperty.GeneratePropertyForString(value as string); } if (entityProperty != null) { properties[getter.Key] = entityProperty; } } return(properties); }
public void Log <TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func <TState, Exception, string> formatter) { if (!IsEnabled(logLevel)) { return; } if (formatter == null) { throw new ArgumentNullException(nameof(formatter)); } var message = formatter(state, exception); string exceptionText = exception?.ToString(); bool hasMessageOverflow = message.Length > overflowThreshold; var properties = new Dictionary <string, EntityProperty> { ["LogLevel"] = EntityProperty.GeneratePropertyForString(logLevel.ToString()), ["Message"] = EntityProperty.GeneratePropertyForString(hasMessageOverflow ? message.Substring(0, overflowThreshold) : message), ["ExceptionText"] = EntityProperty.GeneratePropertyForString(exceptionText), ["EventId"] = EntityProperty.GeneratePropertyForInt(eventId.Id), ["EventName"] = EntityProperty.GeneratePropertyForString(eventId.Name), ["Date"] = EntityProperty.GeneratePropertyForDateTimeOffset(DateTimeOffset.Now), ["LoggerName"] = EntityProperty.GeneratePropertyForString(this.Name), ["IsMessageOverflowed"] = EntityProperty.GeneratePropertyForBool(hasMessageOverflow), }; string requestId = null; var current = AzureScope.Current; while (current != null) { foreach (var item in current.Values) { properties.Add($"Scope{current.StateName}{item.Key}", EntityProperty.CreateEntityPropertyFromObject(item.Value)); if (item.Key == "RequestId") { requestId = (string)item.Value; } } current = current.Parent; } properties["RequestId"] = EntityProperty.GeneratePropertyForString(requestId); var id = timeBasedId.NewId(); var partition = (requestId ?? id).Substring(0, 5); if (message != null || exceptionText != null) { var entity = new DynamicTableEntity( partition, id, null, properties); this.sink.Post(entity); if (hasMessageOverflow) { this.overflowSink.Post(new KeyValuePair <string, string>(id, message)); } } }