将对象转换为StackExchange.Redis中的HashEntry
本文关键字:Redis 中的 HashEntry StackExchange 对象 转换 | 更新日期: 2023-09-27 18:17:32
我想让HashSet在redis使用StackExchange。Redis,但是在db.HashSet()我应该传递HashEntry类型,我如何将对象转换为HashEntry,我知道反射,是否有转换对象的快速代码?
我知道已经6年多了,但是当我搜索时,仍然有太多的信息分布在互联网上。所以我决定写在这里,如果有人需要它。
下面有2个方法。ToHashEntries
用于写对象到redis, ConvertFromRedis
用于读对象到redis。
注意:我使用Newtonsoft.Json
库作为json转换器。
public static HashEntry[] ToHashEntries(object obj)
{
PropertyInfo[] properties = obj.GetType().GetProperties();
return properties
.Where(x => x.GetValue(obj) != null) // <-- PREVENT NullReferenceException
.Select
(
property =>
{
object propertyValue = property.GetValue(obj);
string hashValue;
// This will detect if given property value is
// enumerable, which is a good reason to serialize it
// as JSON!
if (propertyValue is IEnumerable<object>)
{
// So you use JSON.NET to serialize the property
// value as JSON
hashValue = JsonConvert.SerializeObject(propertyValue);
}
else
{
hashValue = propertyValue.ToString();
}
return new HashEntry(property.Name, hashValue);
}
)
.ToArray();
}
public static T ConvertFromRedis<T>(HashEntry[] hashEntries)
{
PropertyInfo[] properties = typeof(T).GetProperties();
var obj = Activator.CreateInstance(typeof(T));
foreach (var property in properties)
{
HashEntry entry = hashEntries.FirstOrDefault(g => g.Name.ToString().Equals(property.Name));
if (entry.Equals(new HashEntry())) continue;
property.SetValue(obj, Convert.ChangeType(entry.Value.ToString(), property.PropertyType));
}
return (T)obj;
}
用法:
public class RedisContext
{
private static RedisContext _redisContext;
private static IDatabase _redis;
private RedisContext()
{
_redis = ConnectionMultiplexer.Connect(Utils.REDIS_HOST).GetDatabase();
}
public static RedisContext GetInstance()
{
if (_redisContext == null)
_redisContext = new RedisContext();
return _redisContext;
}
public void set<T>(string key, T obj)
{
if (typeof(T) == typeof(string))
_redis.StringSet(key, obj.ToString());
else
_redis.HashSet(key, RedisConverter.ToHashEntries(obj));
}
public T get<T>(string key)
{
if (typeof(T) == typeof(string))
return (T)Convert.ChangeType(_redis.StringGet(key), typeof(T));
else
return RedisConverter.ConvertFromRedis<T>(_redis.HashGetAll(key));
}
}
库目前不包括任何映射哈希到/从对象和相关属性的层。如果你想这样做,你必须单独做,可能使用反射之类的东西,但也可能使用FastMember或HyperDescriptor之类的辅助工具。
扩展Kadir Kalkan的回答,如果HashEntry
包含Enum,则解决方案如下。
将property.SetValue(obj, Convert.ChangeType(entry.Value.ToString(), property.PropertyType));
行替换为:
object? propValue;
if (property.PropertyType.IsEnum)
{
propValue = Enum.Parse(property.PropertyType, entry.Value.ToString(), true);
}
else
{
propValue = Convert.ChangeType(entry.Value.ToString(), property.PropertyType);
}
property.SetValue(obj, propValue);