public class MessagePackTranscoder : DefaultTranscoder { protected override ArraySegment<byte> SerializeObject(object value) { return MessagePackSerializer.SerializeUnsafe(value, TypelessContractlessStandardResolver.Instance); } public override T Deserialize<T>(CacheItem item) { return (T)base.Deserialize(item); } protected override object DeserializeObject(ArraySegment<byte> value) { return MessagePackSerializer.Deserialize<object>(value, TypelessContractlessStandardResolver.Instance); } }
庆幸的是,MessagePack有方法可以让我们直接把一个object序列化成ArraySegment,也可以把ArraySegment 反序列化成一个object!!
相比Json和Protobuf,省去了不少操作!!
这个时候,我们有两种方式来使用这个新定义的MessagePackTranscoder。
方式一 :在使用的时候,我们只需要替换前面定义的transcoder变量即可(适用>=2.1.0版本)。
string transcoder = "CachingSerializer.MessagePackTranscoder,CachingSerializer";
注:如果使用方式一来处理,记得将transcoder的拼写不要错,并且要带上命名空间,不然创建的Transcoder会一直是null,从而走的就是Bson了! 本质是 Activator.CreateInstance,应该不用多解释。
方式二:通过依赖注入的方式来处理(适用>=2.1.0.5版本)
private static void InitMemcached(string transcoder = "") { IServiceCollection services = new ServiceCollection(); services.AddEnyimMemcached(options => { options.AddServer("127.0.0.1", 11211); //这里保持空字符串或不赋值,就会走下面的AddSingleton //如果这里赋了正确的值,后面的AddSingleton就不会起作用了 options.Transcoder = transcoder; }); //使用新定义的MessagePackTranscoder services.AddSingleton<ITranscoder, MessagePackTranscoder>(); //others... }
运行之前加个断点,确保真的进了我们重写的方法中。
最后的结果:
Protobuf和Json的,在这里就不一一介绍了,这两个处理起来比MessagePack复杂了不少。可以参考MemcachedTranscoder这个开源项目,也是MessagePack作者写的,虽然是5年前的,但是一样的好用。
对于Redis来说,在调用Set方法时要显式的将我们的值先进行序列化,不那么简洁,所以都会进行一次封装在使用。
对于Memcached来说,在调用Set方法的时候虽然不需要显式的进行序列化,但是有可能要我们自己去实现一个Transcoder,这也是有点麻烦的。
下面给大家推荐一个简单的缓存库来处理这些问题。
使用EasyCaching来简化操作
EasyCaching是笔者在业余时间写的一个简单的开源项目,主要目的是想简化缓存的操作,目前也在不断的完善中。
EasyCaching提供了前面所说的4种序列化方法可供选择:
BinaryFormatter
MessagePack
Json
ProtoBuf
如果这4种都不满足需求,也可以自己写一个,只要实现IEasyCachingSerializer这个接口相应的方法即可。
Redis
在介绍怎么用序列化之前,先来简单看看是怎么用的(用ASP.NET Core Web API做演示)。
添加Redis相关的nuget包
Install-Package EasyCaching.Redis
修改Startup
public class Startup { //... public void ConfigureServices(IServiceCollection services) { //other services. //Important step for Redis Caching services.AddDefaultRedisCache(option=> { option.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379)); option.Password = ""; }); } }
然后在控制器中使用:
[Route("api/[controller]")] public class ValuesController : Controller { private readonly IEasyCachingProvider _provider; public ValuesController(IEasyCachingProvider provider) { this._provider = provider; } [HttpGet] public string Get() { //Set _provider.Set("demo", "123", TimeSpan.FromMinutes(1)); //Get without data retriever var res = _provider.Get<string>("demo"); _provider.Set("product:1", new Product { Id = 1, Name = "name"}, TimeSpan.FromMinutes(1)) var product = _provider.Get<Product>("product:1"); return $"{res.Value}-{product.Value.Id}-{product.Value.Name}"; } }
使用的时候,在构造函数对IEasyCachingProvider进行依赖注入即可。
Redis默认用了BinaryFormatter来进行序列化。
下面我们要如何去替换我们想要的新的序列化方法呢?
以MessagePack为例,先通过nuget安装package
Install-Package EasyCaching.Serialization.MessagePack
然后只需要在ConfigureServices方法中加上下面这句就可以了。
public void ConfigureServices(IServiceCollection services) { //others.. services.AddDefaultMessagePackSerializer(); }
Memcached
同样先来简单看看是怎么用的(用ASP.NET Core Web API做演示)。
添加Memcached的nuget包
Install-Package EasyCaching.Memcached
修改Startup