예제 #1
0
        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));
                }
            };
        }
예제 #2
0
        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));
                }
            };
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
            }
        }
예제 #6
0
        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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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());
        }
예제 #11
0
        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);
            }
        }
예제 #13
0
        public void JsonFallback_WorkWell()
        {
            var converter = new RedisTypeConverter();

            AssertConversionEqual(converter, new { Value = "123" }, "{\"Value\":\"123\"}");
        }
예제 #14
0
        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());
        }