今回のレッスンでは、クラスオブジェクトの保存方法を学び、オブジェクトの保存と読み出しを実装します。
このコードは Memcached による基本型(int/bool)と自作クラスオブジェクトの保存を示しており、陥りやすい重要なポイントを紹介します。
自作エンティティクラスには
[Serializable]属性を付与する必要があります。付けないとシリアライズに失敗し、オブジェクト取得時にnullが返ります。
誤った実装
static void Main(string[] args)
{
MemcachedClient mClient = new MemcachedClient();
// 基本型の保存・取得(int、boolは標準対応、シリアライズ属性不要)
mClient.Store(StoreMode.Set, "clicks", 1);
var clicks = mClient.Get<int>("clicks");
mClient.Store(StoreMode.Set, "isOk", true);
var isOk = mClient.Get<bool>("isOk");
// 自作オブジェクト保存
var person = new Person { Id = 1, Name = "Jackson", AddTime = DateTime.Now };
mClient.Store(StoreMode.Set, "person", person);
var p = mClient.Get<Person>("person"); // ここでnullが返る
Console.Read();
}
// 【NG】[Serializable] が不足
class Person
{
public int Id { set; get; }
public string Name { set; get; }
public DateTime AddTime { set; get; }
}Code language: JavaScript (javascript)
発生する現象
var p = mClient.Get<Person>("person"); の実行結果が null になります。
原因:EnyimMemcached は既定で .NET のバイナリシリアライズを利用します。[Serializable]属性のないクラスはシリアライズできず、キャッシュから正常にデシリアライズできません。
正しい実装
エンティティクラスにシリアライズ属性を追加します。
[Serializable] // 必須の属性
public class Person
{
public int Id { set; get; }
public string Name { set; get; }
public DateTime AddTime { set; get; }
}Code language: JavaScript (javascript)
追加後は Get<Person>("person") でオブジェクトを正しく取得できます。
補足情報
// ジェネリック取得:Get<T> 推奨、自動で型変換される
var p = mClient.Get<Person>("person");
// 非ジェネリックGet:objectが返るので手動でキャストが必要
var p2 = mClient.Get("person");Code language: JavaScript (javascript)
Get<T>(key):ジェネリックメソッド、優先して使用。取得失敗時は型の既定値を返す(参照型はnull)Get(key):生のobjectを返す、自分で型キャストを行う必要あり
完全なサンプルコード
using Enyim.Caching;
using Enyim.Caching.Memcached;
using System;
[Serializable]
public class Person
{
public int Id { set; get; }
public string Name { set; get; }
public DateTime AddTime { set; get; }
}
class Program
{
static void Main(string[] args)
{
MemcachedClient mClient = new MemcachedClient();
mClient.Store(StoreMode.Set, "clicks", 1);
var clicks = mClient.Get<int>("clicks");
mClient.Store(StoreMode.Set, "isOk", true);
var isOk = mClient.Get<bool>("isOk");
var person = new Person { Id = 1, Name = "Jackson", AddTime = DateTime.Now };
mClient.Store(StoreMode.Set, "person", person);
var p = mClient.Get<Person>("person");
Console.WriteLine(p.Name); // Jackson が出力される
Console.Read();
}
}Code language: JavaScript (javascript)
オブジェクト保存