private static void BuildTrackableListProperty <TValue>(PropertyItem item, RedisTypeConverter typeConverter) { var mapper = new TrackableListRedisMapper <TValue>(typeConverter); item.Mapper = mapper; item.CreateAsync = (db, container, key) => { var list = (IList <TValue>)item.PropertyInfo.GetValue(container); return(mapper.CreateAsync(db, list, key.Append(item.KeySuffix))); }; item.DeleteAsync = (db, key) => { return(mapper.DeleteAsync(db, key.Append(item.KeySuffix))); }; item.LoadAsync = async(db, container, key) => { var list = (IList <TValue>)item.PropertyInfo.GetValue(container); // when there is no entry for list, it is regarded as an empty list. await mapper.LoadAsync(db, list, key.Append(item.KeySuffix)); return(true); }; item.SaveAsync = async(db, tracker, key) => { var valueTracker = (TrackableListTracker <TValue>)item.TrackerPropertyInfo.GetValue(tracker); if (valueTracker.HasChange) { await mapper.SaveAsync(db, valueTracker, key.Append(item.KeySuffix)); } }; }
private static void BuildTrackablePocoProperty <TPoco>(PropertyItem item, RedisTypeConverter typeConverter) where TPoco : ITrackablePoco <TPoco> { var mapper = new TrackablePocoRedisMapper <TPoco>(typeConverter); item.Mapper = mapper; item.CreateAsync = (db, container, key) => { var value = (TPoco)item.PropertyInfo.GetValue(container); return(mapper.CreateAsync(db, value, key.Append(item.KeySuffix))); }; item.DeleteAsync = (db, key) => { return(mapper.DeleteAsync(db, key.Append(item.KeySuffix))); }; item.LoadAsync = (db, container, key) => { var value = (TPoco)item.PropertyInfo.GetValue(container); // when there is no entry for poco, it is regarded as non-existent container. return(mapper.LoadAsync(db, value, key.Append(item.KeySuffix))); }; item.SaveAsync = async(db, tracker, key) => { var valueTracker = (TrackablePocoTracker <TPoco>)item.TrackerPropertyInfo.GetValue(tracker); if (valueTracker.HasChange) { await mapper.SaveAsync(db, valueTracker, key.Append(item.KeySuffix)); } }; }
public void Nullable_WorkWell() { var converter = new RedisTypeConverter(); AssertConversionEqual(converter, (bool?)null, RedisValue.Null); AssertConversionEqual(converter, (bool?)true, true); AssertConversionEqual(converter, (int?)null, RedisValue.Null); AssertConversionEqual(converter, (int?)100, 100); }
public void RegisterTypeConverterAsExplicitType_WorkWell() { var converter = new RedisTypeConverter(); converter.Register( v => ('`' + v + '`'), v => ((string)v).Trim('`')); AssertConversionEqual(converter, "Value", "`Value`"); }
public TrackableListRedisMapper(RedisTypeConverter typeConverter = null) { if (typeConverter == null) { typeConverter = RedisTypeConverter.Instance; } _valueToRedisValue = typeConverter.GetToRedisValueFunc <T>(); _redisValueToValue = typeConverter.GetFromRedisValueFunc <T>(); if (_valueToRedisValue == null || _redisValueToValue == null) { throw new ArgumentException("Cannot find type converter. Type=" + typeof(T).Name); } }
public TrackableContainerRedisMapper(RedisTypeConverter typeConverter = null) { if (typeConverter == null) { typeConverter = RedisTypeConverter.Instance; } _trackableType = TrackableResolver.GetContainerTrackerType(typeof(T)); if (_trackableType == null) { throw new ArgumentException($"Cannot find tracker type of '{nameof(T)}'"); } _items = ConstructPropertyItems(typeConverter); }
public TrackableContainerHashesRedisMapper(RedisTypeConverter typeConverter = null) { if (typeConverter == null) { typeConverter = RedisTypeConverter.Instance; } _trackableType = TrackableResolver.GetContainerTrackerType(typeof(T)); if (_trackableType == null) { throw new ArgumentException($"Cannot find tracker type of '{nameof(T)}'"); } _items = ConstructPropertyItems(typeConverter); _fieldNameToItemMap = _items.ToDictionary(x => x.FieldName, y => y); }
public TrackablePocoRedisMapper(RedisTypeConverter typeConverter = null) { if (typeConverter == null) { typeConverter = RedisTypeConverter.Instance; } _trackableType = TrackableResolver.GetPocoTrackerType(typeof(T)); if (_trackableType == null) { throw new ArgumentException($"Cannot find type '{typeof(T).Name}'"); } _items = ConstructPropertyItems(typeConverter); _fieldNameToItemMap = _items.ToDictionary(x => x.FieldName, y => y); _propertyInfoToItemMap = _items.ToDictionary(x => x.PropertyInfo, y => y); }
public void DefaultConverter_WorkWell() { var converter = new RedisTypeConverter(); AssertConversionEqual(converter, true); AssertConversionEqual(converter, (short)1); AssertConversionEqual(converter, (int)1); AssertConversionEqual(converter, (long)1); AssertConversionEqual(converter, 'c'); AssertConversionEqual(converter, "string:\xAC00"); AssertConversionEqual(converter, 3.141592f); AssertConversionEqual(converter, 3.1415927410125732); AssertConversionEqual(converter, new byte[] { 0, 1, 2 }); AssertConversionEqual(converter, new DateTime(2001, 1, 1, 1, 1, 1)); AssertConversionEqual(converter, new DateTimeOffset(2001, 1, 1, 1, 1, 1, TimeSpan.FromHours(2))); AssertConversionEqual(converter, new TimeSpan(1, 2, 3)); AssertConversionEqual(converter, Guid.NewGuid()); }
private static PropertyItem[] ConstructPropertyItems(RedisTypeConverter typeConverter) { var trackerType = TrackerResolver.GetDefaultTracker(typeof(T)); var items = new List <PropertyItem>(); foreach (var property in typeof(T).GetProperties()) { var fieldName = property.Name; var attr = property.GetCustomAttribute <TrackablePropertyAttribute>(); if (attr != null) { if (attr["redis.ignore"] != null) { continue; } fieldName = attr["redis.field:"] ?? fieldName; } var item = new PropertyItem { Name = property.Name, FieldName = fieldName, PropertyInfo = property, TrackerPropertyInfo = trackerType.GetProperty(property.Name + "Tracker"), ConvertToRedisValue = typeConverter.GetToRedisValueFunc(property.PropertyType), ConvertFromRedisValue = typeConverter.GetFromRedisValueFunc(property.PropertyType), }; if (item.TrackerPropertyInfo == null) { throw new ArgumentException($"Cannot find tracker type of '{property.Name}'"); } if (item.ConvertToRedisValue == null || item.ConvertFromRedisValue == null) { throw new ArgumentException("Cannot find type converter. Property=" + property.Name); } items.Add(item); } return(items.ToArray()); }
private void AssertConversionEqual <T>(RedisTypeConverter converter, T value, RedisValue?expectedRedisValue = null) { // check from(to(V)) == V (explicit type version) var rv1 = converter.GetToRedisValueFunc <T>()(value); var nv1 = converter.GetFromRedisValueFunc <T>()(rv1); Assert.Equal(value, nv1); // check from(to(V)) == V (object type version) var rv2 = converter.GetToRedisValueFunc(typeof(T))(value); var nv2 = converter.GetFromRedisValueFunc(typeof(T))(rv2); Assert.Equal(value, nv2); // check to1(V) == to2(V) Assert.Equal(rv1, rv2); if (expectedRedisValue != null) { Assert.Equal(expectedRedisValue.Value, rv1); } }
public TrackableDictionaryRedisMapper(RedisTypeConverter typeConverter = null) { if (typeConverter == null) { typeConverter = RedisTypeConverter.Instance; } _keyToRedisValue = typeConverter.GetToRedisValueFunc <TKey>(); _redisValueToKey = typeConverter.GetFromRedisValueFunc <TKey>(); if (_keyToRedisValue == null || _redisValueToKey == null) { throw new ArgumentException("Cannot find type converter. Type=" + typeof(TKey).Name); } _valueToRedisValue = typeConverter.GetToRedisValueFunc <TValue>(); _redisValueToValue = typeConverter.GetFromRedisValueFunc <TValue>(); if (_valueToRedisValue == null || _redisValueToValue == null) { throw new ArgumentException("Cannot find type converter. Type=" + typeof(TValue).Name); } }
public void JsonFallback_WorkWell() { var converter = new RedisTypeConverter(); AssertConversionEqual(converter, new { Value = "123" }, "{\"Value\":\"123\"}"); }
private static PropertyItem[] ConstructPropertyItems(RedisTypeConverter typeConverter) { var trackerType = TrackerResolver.GetDefaultTracker(typeof(T)); var items = new List <PropertyItem>(); foreach (var property in typeof(T).GetProperties()) { var keySuffix = ":" + property.Name; var attr = property.GetCustomAttribute <TrackablePropertyAttribute>(); if (attr != null) { if (attr["redis.ignore"] != null) { continue; } keySuffix = attr["redis.keysuffix:"] ?? keySuffix; } var item = new PropertyItem { Name = property.Name, KeySuffix = keySuffix, PropertyInfo = property, TrackerPropertyInfo = trackerType.GetProperty(property.Name + "Tracker") }; if (item.TrackerPropertyInfo == null) { throw new ArgumentException($"Cannot find tracker type of '{property.Name}'"); } if (TrackableResolver.IsTrackablePoco(property.PropertyType)) { typeof(TrackableContainerRedisMapper <T>) .GetMethod("BuildTrackablePocoProperty", BindingFlags.Static | BindingFlags.NonPublic) .MakeGenericMethod(TrackableResolver.GetPocoType(property.PropertyType)) .Invoke(null, new object[] { item, typeConverter }); } else if (TrackableResolver.IsTrackableDictionary(property.PropertyType)) { typeof(TrackableContainerRedisMapper <T>) .GetMethod("BuildTrackableDictionaryProperty", BindingFlags.Static | BindingFlags.NonPublic) .MakeGenericMethod(property.PropertyType.GetGenericArguments()) .Invoke(null, new object[] { item, typeConverter }); } else if (TrackableResolver.IsTrackableSet(property.PropertyType)) { typeof(TrackableContainerRedisMapper <T>) .GetMethod("BuildTrackableSetProperty", BindingFlags.Static | BindingFlags.NonPublic) .MakeGenericMethod(property.PropertyType.GetGenericArguments()) .Invoke(null, new object[] { item, typeConverter }); } else if (TrackableResolver.IsTrackableList(property.PropertyType)) { typeof(TrackableContainerRedisMapper <T>) .GetMethod("BuildTrackableListProperty", BindingFlags.Static | BindingFlags.NonPublic) .MakeGenericMethod(property.PropertyType.GetGenericArguments()) .Invoke(null, new object[] { item, typeConverter }); } else { throw new InvalidOperationException("Cannot resolve property: " + property.Name); } items.Add(item); } return(items.ToArray()); }