我想让 HashSet 在 redis 中使用 StackExchange.Redis,但是在 db.HashSet() 中我应该传递 HashEntry 类型,我如何将对象转换为 HashEntry,我知道反射,是否有转换对象的快速代码?
问问题
3885 次
3 回答
6
我知道这已经 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));
}
}
于 2021-03-23T08:33:36.160 回答
3
该库目前不包含任何用于将哈希映射到对象和相关属性的层。如果你想这样做,你必须单独做,也许使用反射之类的东西,但也许使用像 FastMember 或 HyperDescriptor 这样的辅助工具。
于 2014-08-12T14:33:05.647 回答
3
扩展 Kadir Kalkan 的答案HashEntry
,如果包含枚举,这里是解决方案。
将行替换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);
于 2021-04-22T22:01:30.843 回答