この章の内容は次のとおりです。
IPortableObject
を実装する各クラスは、自身の状態をPOFデータ・ストリームにシリアライズし、POFデータ・ストリームからデシリアライズできます。IPofSerializer
実装を作成することで、ユーザー定義型のポータブル・シリアライズを外部化できます。親トピック: .NET Extendクライアントの作成
POFでは、あらゆる一般的な.NET型が即時利用可能な状態でサポートされます。カスタムの.NETクラスも次の手順でPOFストリームにシリアライズできます:
IPortableObject
インタフェースを実装する.NETクラスを作成します。「IPortableObject実装の作成」を参照してください。
同様に、PortableObjectインタフェースを実装する、対応するJavaクラスを作成します。「PortableObject実装の作成(Java)」を参照してください。
カスタムの.NETクラスをクライアントに登録します。「.NETクライアントでのカスタム型の登録」を参照してください。
Coherence*Extendクラスタ化サービスを実行している各サーバーにカスタムのJavaクラスを登録します。「クラスタでのカスタム型の登録」を参照してください。
ここまでの手順が完了すると、組込みのデータ型と同じようにカスタムの.NETクラスをCoherenceキャッシュにキャッシュできるようになります。さらに対応するJavaクラスを使用すれば、それらの型をCoherenceまたはCoherence*Extend JVMから取得し、操作して、格納できます。
IPortableObject
を実装する各クラスは、自身の状態をPOFデータ・ストリームにシリアライズし、POFデータ・ストリームからデシリアライズできます。この処理は、ReadExternal
メソッド(デシリアライズ)およびWriteExternal
メソッド(シリアライズ)で行われます。概念上は、すべてのユーザー定義型が0個以上の索引付き値(プロパティ)で構成されており、それらが1つずつPOFデータ・ストリームから読み取られ、POFデータ・ストリームに書き込まれます。移植可能なクラスには、IPortableObject
インタフェースの実装が必要であること以外の唯一の要件として、デフォルト・コンストラクタが必要です。これにより、POFデシリアライザで、デシリアライズ時にクラスのインスタンスを作成できるようになります。例18-1は、移植可能なユーザー定義クラスを示しています。
例18-1 移植可能なユーザー定義クラス
public class ContactInfo : IPortableObject { private string name; private string street; private string city; private string state; private string zip; public ContactInfo() {} public ContactInfo(string name, string street, string city, string state, string zip) { Name = name; Street = street; City = city; State = state; Zip = zip; } public void ReadExternal(IPofReader reader) { Name = reader.ReadString(0); Street = reader.ReadString(1); City = reader.ReadString(2); State = reader.ReadString(3); Zip = reader.ReadString(4); } public void WriteExternal(IPofWriter writer) { writer.WriteString(0, Name); writer.WriteString(1, Street); writer.WriteString(2, City); writer.WriteString(3, State); writer.WriteString(4, Zip); } // property definitions ommitted for brevity }
POFの使用によって、並列のJava実装を必要とせずに、キーおよび値オブジェクトをクラスタ内に格納できます。これは、基本的なgetとputベースの操作を実行する場合に適しています。さらに、PofExtractor
とPofUpdater
APIにより、Coherenceの非プリミティブ・タイプを使用するときの柔軟性が向上します。多くの拡張クライアントの場合、グリッド内に対応するJavaクラスは不要です。POFエクストラクタとPOFアップデータはバイナリをナビゲートできるため、キーと値全体をオブジェクト形式にデシリアライズしなくても済みます。これは、索引付けする値をPOFエクストラクタを使用してプルするだけで索引付けできることを意味します。
並列のJava実装の組込みが必要になる状況
Javaベースのキャッシュ・サーバーが、データ・オブジェクトのシリアライズ表現を保持するだけでなく、データ・オブジェクトと直接対話する必要がある場合は、並列のJava実装が必要です。たとえば、キャッシュ・ストアを使用するときJavaクラスは必要です。この場合、キーと値のデシリアライズ・バージョンがキャッシュ・ストアに渡され、バックエンドに書き込まれます。さらに、オブジェクトへの直接アクセスが必要な場合、問合せ、フィルタ、入力プロセッサおよびアグリゲータはJava実装が必要です。
Java実装が必要な場合は、実装はキャッシュ・サーバーにある必要があります。JavaバージョンのPOFでシリアライズ可能にする方法は、「PortableObject実装の作成(Java)」で説明されています。
キーの関連付けチェックの遅延
キー・クラスは、クラスタ側Java実装を必要としません。これはIKeyAssociation
インタフェースを使用してデータのアフィニティを指定している場合でも同様です。キー・クラスは、クライアント側でチェックされ、修飾されたバイナリがクラスタによって作成および使用されます。ただし、キーの関連付けをJavaキー・クラスに依存している既存のクライアント実装は、Javaキー・クラスの使用を強制するためにdefer-key-association-check
パラメータを設定する必要があります。キーの関連付けを使用する既存クライアント・アプリケーションで、クライアント側のキー・バイナリを利用する場合は、getAssociatedKey()
実装を既存のJavaクラスから対応するクライアント・クラスに移植する必要があります(IKeyAssociation.AssociatedKey
を参照)。
キーの関連付け処理をExtendクライアントによってではなくクラスタ側で実行するには、クライアント側キャッシュの構成で<remote-cache-scheme>
要素の<defer-key-association-check>
要素をtrue
に設定します。次に例を示します。
<remote-cache-scheme> ... <defer-key-association-check>true</defer-key-association-check> </remote-cache-scheme>
注意:
パラメータがtrue
に設定されている場合、Javaキー・クラス実装は、キーの関連付けを使用していない場合でも、クラスタに存在する必要があります。
この項には次のトピックが含まれます:
Javaでの移植可能なクラスの実装は、.NETでの実装と非常によく似ています。例18-2は、例18-1の.NETクラスをJavaで実現した場合を示しています。
例18-2 Javaでのユーザー定義クラス
public class ContactInfo implements PortableObject { private String m_sName; private String m_sStreet; private String m_sCity; private String m_sState; private String m_sZip; public ContactInfo() { } public ContactInfo(String sName, String sStreet, String sCity, String sState, String sZip) { setName(sName); setStreet(sStreet); setCity(sCity); setState(sState); setZip(sZip); } public void readExternal(PofReader reader) throws IOException { setName(reader.readString(0)); setStreet(reader.readString(1)); setCity(reader.readString(2)); setState(reader.readString(3)); setZip(reader.readString(4)); } public void writeExternal(PofWriter writer) throws IOException { writer.writeString(0, getName()); writer.writeString(1, getStreet()); writer.writeString(2, getCity()); writer.writeString(3, getState()); writer.writeString(4, getZip()); } // accessor methods omitted for brevity }
次の例は、POF構成ファイルを示しています。
<?xml version="1.0"?> <pof-config xmlns="http://schemas.tangosol.com/pof"> <user-type-list> <!-- include all "standard" Coherence POF user types --> <include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml </include> <!-- include all application POF user types --> <user-type> <type-id>1001</type-id> <class-name>My.Example.ContactInfo, MyAssembly</class-name> </user-type> </user-type-list> </pof-config>
次の点に注意してください。
カスタム型の型識別子は1001以上の数値で始まる必要があります。1000より小さい数値は内部使用に予約されています。この例に示すように、<user-type-list>
にはcoherence-pof-config.xml
ファイルが含まれます。これにはCoherence固有のユーザー型が定義されており、そのユーザー型をすべてのPOF構成ファイルに含める必要があります。
class-name要素内では完全に修飾された型名を指定する必要はありません。型とアセンブリ名を指定すれば十分です。
型識別子とカスタム型の間のマッピングを構成したら、キャッシュ構成ディスクリプタにserializer要素を追加して、それらのマッピングを使用するようCoherence for .NETを構成する必要があります。次の各例では、ユーザーの型マッピングがmy-dotnet-pof-config.xml
ファイルに保存されていることを前提とします。
<remote-cache-scheme> <scheme-name>extend-direct</scheme-name> <service-name>ExtendTcpCacheService</service-name> <initiator-config> ... <serializer> <class-name>Tangosol.IO.Pof.ConfigurablePofContext, Coherence </class-name> <init-params> <init-param> <param-type>string</param-type> <param-value>my-dotnet-pof-config.xml</param-value> </init-param> </init-params> </serializer> </initiator-config> </remote-cache-scheme>
シリアライザを明示的に指定しない場合は、ConfigurablePofContext
型がPOFシリアライザとして使用されます。これはpof-config.xml
というデフォルトの構成ファイルを使用します。Coherence .NETアプリケーションでは、アプリケーションのデプロイ先フォルダと、Webアプリケーションの場合はWebアプリケーションのルートの両方で、デフォルトのPOF構成ファイルが検索されます。POF構成ファイルが見つからない場合は、Coherence for .NETアプリケーション構成ファイルのpof-config
要素の内容によるファイルの特定が試行されます。次に例を示します。
<?xml version="1.0"?> <configuration> <configSections> <section name="coherence" type="Tangosol.Config.CoherenceConfigHandler, Coherence"/> </configSections> <coherence> <pof-config>my-dotnet-pof-config.xml</pof-config> </coherence> </configuration>
クラスタ側のPOF構成ファイルのサンプル(my-java-pof-config.xml
)を次に示します。
<?xml version="1.0"?> <pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config" xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config coherence-pof-config.xsd"> <user-type-list> <!-- include all "standard" Coherence POF user types --> <include>coherence-pof-config.xml</include> <!-- include all application POF user types --> <user-type> <type-id>1001</type-id> <class-name>com.mycompany.example.ContactInfo</class-name> </user-type> </user-type-list> </pof-config>
カスタム型を追加したら、オブジェクトのシリアライズ時に各自のPOF構成ファイルが使用されるようサーバーを構成する必要があります。
<proxy-scheme> <service-name>ExtendTcpProxyService</service-name> <acceptor-config> ... <serializer> <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name> <init-params> <init-param> <param-type>string</param-type> <param-value>my-java-pof-config.xml</param-value> </init-param> </init-params> </serializer> </acceptor-config> ... </proxy-scheme>
IPortableObject
インタフェースのかわりにIEvolvablePortableObject
インタフェースを実装することで、このサポートが実現します。 IEvolvablePortableObject
インタフェースは、IPortableObject
とIEvolvable
の両方のインタフェースを拡張するマーカー・インタフェースです。IEvolvable
インタフェースは、型のバージョニングをサポートする3つのプロパティを追加します。IEvolvable
クラスには整数のバージョン識別子n (n >= 0)が含まれていますシリアライズされた形式のIEvolvable
クラスのコンテンツ、セマンティクス、またはそれら両方が変更されると、このバージョン識別子が引き上げられます。2つのバージョン識別子n1
とn2
は、n1
==
n2
であれば同じバージョンを示し、n2
>
n1
であればn2
のバージョンがn1
のバージョンより新しいことを示します。
IEvolvable
インタフェースは、データの追加による型の進化をサポートするように設計されています。あるデータに前のバージョンの型が依存している場合、そのデータを安全に削除することはできません。同様に、データの前の構造またはセマンティクスに前のバージョンの型が依存している場合、そのデータの構造またはセマンティクスを前のバージョンから安全に変更することはできません。
IEvolvable
オブジェクトがデシリアライズされる場合は、新しいバージョンの型に追加された未知のデータ、およびそのデータ形式のバージョン識別子が保持されます。その後、このIEvolvableオブジェクトがシリアライズされると、保持されたバージョン識別子と未知の将来データがオブジェクトに取り込まれます。
古いバージョンを示すバージョン識別子を持つデータ・ストリームからIEvolvable
オブジェクトをデシリアライズする場合は、その古いバージョン以降に追加されたデータ・フィールドやプロパティの値をデフォルトに設定し、計算する必要があります。その後、このIEvolvable
オブジェクトがシリアライズされると、そのバージョン識別子と全データがオブジェクトに取り込まれます。この場合は未知の将来データがないことに注意してください。将来データは、データ・ストリームのバージョンがIEvolvable型のバージョンよりも新しい場合にのみ存在します。
例18-3は、クラスの進化をサポートするように.NET型のContactInfo
を変更する方法を示しています。
例18-3 クラスの進化をサポートするようにクラスを変更する
public class ContactInfo : IEvolvablePortableObject { private string name; private string street; private string city; private string state; private string zip; // IEvolvable members private int version; private byte[] data; public ContactInfo() {} public ContactInfo(string name, string street, string city, string state, string zip) { Name = name; Street = street; City = city; State = state; Zip = zip; } public void ReadExternal(IPofReader reader) { Name = reader.ReadString(0); Street = reader.ReadString(1); City = reader.ReadString(2); State = reader.ReadString(3); Zip = reader.ReadString(4); } public void WriteExternal(IPofWriter writer) { writer.WriteString(0, Name); writer.WriteString(1, Street); writer.WriteString(2, City); writer.WriteString(3, State); writer.WriteString(4, Zip); } public int DataVersion { get { return version; } set { version = value; } } public byte[] FutureData { get { return data; } set { data = value; } } public int ImplVersion { get { return 0; } } // property definitions ommitted for brevity }
同様に、Java型のContactInfo
は、EvolvablePortableObject
インタフェースを実装することでクラスの進化をサポートするように変更できます。
例18-4 クラスの進化をサポートするようにJava型のクラスを変更する
public class ContactInfo implements EvolvablePortableObject { private String m_sName; private String m_sStreet; private String m_sCity; private String m_sState; private String m_sZip; // Evolvable members private int m_nVersion; private byte[] m_abData; public ContactInfo() {} public ContactInfo(String sName, String sStreet, String sCity, String sState, String sZip) { setName(sName); setStreet(sStreet); setCity(sCity); setState(sState); setZip(sZip); } public void readExternal(PofReader reader) throws IOException { setName(reader.readString(0)); setStreet(reader.readString(1)); setCity(reader.readString(2)); setState(reader.readString(3)); setZip(reader.readString(4)); } public void writeExternal(PofWriter writer) throws IOException { writer.writeString(0, getName()); writer.writeString(1, getStreet()); writer.writeString(2, getCity()); writer.writeString(3, getState()); writer.writeString(4, getZip()); } public int getDataVersion() { return m_nVersion; } public void setDataVersion(int nVersion) { m_nVersion = nVersion; } public Binary getFutureData() { return m_binData; } public void setFutureData(Binary binFuture) { m_binData = binFuture; } public int getImplVersion() { return 0; } // accessor methods omitted for brevity }
IPofSerializer
実装を作成することで、ユーザー定義型のポータブル・シリアライズを外部化できます。
例18-5は、ContactInfo
のIPofSerializer
インタフェースの実装を示しています。
例18-5 .NET型のIPofSerializerの実装
public class ContactInfoSerializer : IPofSerializer { public object Deserialize(IPofReader reader) { string name = reader.ReadString(0); string street = reader.ReadString(1); string city = reader.ReadString(2); string state = reader.ReadString(3); string zip = reader.ReadString(4); ContactInfo info = new ContactInfo(name, street, city, state, zip); info.DataVersion = reader.VersionId; info.FutureData = reader.ReadRemainder(); return info; } public void Serialize(IPofWriter writer, object o) { ContactInfo info = (ContactInfo) o; writer.VersionId = Math.Max(info.DataVersion, info.ImplVersion); writer.WriteString(0, info.Name); writer.WriteString(1, info.Street); writer.WriteString(2, info.City); writer.WriteString(3, info.State); writer.WriteString(4, info.Zip); writer.WriteRemainder(info.FutureData); } }
Java型のContactInfo
のPofSerializer
インタフェースの実装は次のようになります。
例18-6 Java型クラスのPofSerializerの実装
public class ContactInfoSerializer implements PofSerializer { public Object deserialize(PofReader in) throws IOException { String sName = in.readString(0); String sStreet = in.readString(1); String sCity = in.readString(2); String sState = in.readString(3); String sZip = in.readString(4); ContactInfo info = new ContactInfo(sName, sStreet, sCity, sState, sZip); info.setDataVersion(in.getVersionId()); info.setFutureData(in.readRemainder()); return info; } public void serialize(PofWriter out, Object o) throws IOException { ContactInfo info = (ContactInfo) o; out.setVersionId(Math.max(info.getDataVersion(), info.getImplVersion())); out.writeString(0, info.getName()); out.writeString(1, info.getStreet()); out.writeString(2, info.getCity()); out.writeString(3, info.getState()); out.writeString(4, info.getZip()); out.writeRemainder(info.getFutureData()); } }
.NET型のContactInfo
のIPofSerializer
実装を登録するには、POF構成ファイルのContactInfo
ユーザー定義型に関するuser-type要素で、serializer要素内にIPofSerializer
のクラス名を指定します。次に例を示します。
<?xml version="1.0"?> <pof-config xmlns="http://schemas.tangosol.com/pof" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.tangosol.com/pof assembly://Coherence/Tangosol.Config/pof-config.xsd"> <user-type-list> <!-- include all "standard" Coherence POF user types --> <include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml </include> <!-- include all application POF user types --> <user-type> <type-id>1001</type-id> <class-name>My.Example.ContactInfo, MyAssembly</class-name> <serializer> <class-name>My.Example.ContactInfoSerializer, MyAssembly</class-name> </serializer> </user-type> </user-type-list> </pof-config>
同様に、Java型のContactInfo
のPofSerializer
実装を登録できます。
<?xml version="1.0"?> <pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config" xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config coherence-pof-config.xsd"> <user-type-list> <!-- include all "standard" Coherence POF user types --> <include>example-pof-config.xml</include> <!-- include all application POF user types --> <user-type> <type-id>1001</type-id> <class-name>com.mycompany.example.ContactInfo</class-name> <serializer> <class-name>com.mycompany.example.ContactInfoSerializer</class-name> </serializer> </user-type> </user-type-list> </pof-config>
参照を使用することで、同じオブジェクトを複数回エンコーディングすることを防ぎ、データサイズを削減できます。一般に、参照を使用するのは、サイズの大きな多数のオブジェクトが複数回生成されるときや、オブジェクトでネストや循環データ構造が使用されるときです。ただし、大量のデータがあり、繰返しが少ないアプリケーションの場合、オブジェクト参照を使用してもオブジェクトのIDや参照の追跡によって生じるオーバーヘッドのために、最小限の利点しかありません。
オブジェクト・アイデンティティおよび参照の使用には次の制限があります。
オブジェクト参照には、ユーザー定義のオブジェクト型のみがサポートされています。
IEvolvable
オブジェクトでは、オブジェクト参照はサポートされていません。
キーでは、オブジェクト参照はサポートされていません。
参照をサポートしていないPOFコンテキストによって記述されたオブジェクトは、参照をサポートするPOFコンテキストで読み込むことができません。また、この逆の場合も同様です。
POFエクストラクタを使用して、オブジェクト・アイデンティティおよび参照を使用するPOFオブジェクトを問い合せることはできません。かわりに、IValueExtractor
APIを使用してオブジェクト値を問い合せるか、またはオブジェクト参照を無効にしてください。
オブジェクト参照を使用するとき、IPofNavigator
およびIPofValue
APIの使用には次の制約があります。
読取り操作のみ許可されます。書込み操作はUnsupportedOperationException
となります。
ユーザー・オブジェクトは非共通コレクションでアクセスできますが、共通コレクションではアクセスできません。
読取り操作については、オブジェクトがデータ・ストリームで複数回出現する場合、オブジェクトが最初に出現した場所で読み取られてから、次のデータの部分で読み取られる必要があります。そうでない場合は、IOException: missing identity:
<ID>
がスローされます。たとえば、リストが3つあり、そのすべてが同じPersonオブジェクトp
を含む場合。p
オブジェクトは、最初のリストで読み取られてから2番目または3番目のリストで読み取られる必要があります。
この項には次のトピックが含まれます:
オブジェクト参照は、デフォルトでは無効になっており、SimplePofContext
クラスを使用するときにpof-config.xml
構成ファイル内か、プログラムによって有効にする必要があります。
POF構成ファイルでオブジェクト参照を有効にするには、<pof-config>
要素内に<enable-references>
要素を含めて、値をtrue
に設定します。次に例を示します。
<?xml version="1.0"?> <pof-config xmlns="http://schemas.tangosol.com/pof" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.tangosol.com/pof assembly://Coherence/Tangosol.Config/pof-config.xsd"> ... <enable-references>true</enable-references> </pof-config>
SimplePofContext
クラスの使用時にオブジェクト参照を有効にするには、setReferenceEnabled
メソッドをコールして、true
に設定します。次に例を示します。
SimplePofContext ctx = new SimplePofContext(); ctx.IsReferenceEnabled = true;
循環構造のオブジェクトやネストされたオブジェクトは、オブジェクトの作成時に手動でIDを登録する必要があります。これを行わないと、親を参照する子が、参照マップで親のIDを検出しません。オブジェクトのIDは、Tangosol.IO.Pof.IPofReader.RegisterIdentity
メソッドを使用し、デシリアライズ・ルーチンでシリアライザから登録できます。
次の例では、循環参照を含んだ2つのオブジェクト(Customer
およびProduct
)と、Customer
オブジェクトのIDを登録するシリアライザ実装を示しています。
Customer
オブジェクトの定義は次のとおりです。
public class Customer { String m_name; Product m_product; public Customer(String name) { m_name = name; } public Customer(String name, Product product) { m_name = name; m_product = product; } public String getName() { return m_name; } public Product getProduct() { return m_product; } public void setProduct(Product product) { m_product = product; } }
Product
オブジェクトの定義は次のとおりです。
public class Product { private Customer m_customer; public Product(Customer customer) { m_customer = customer; } public Customer getCustomer() { return m_customer; } }
デシリアライズの間にIDを登録するシリアライザ実装の定義は次のとおりです。
public class CustomerSerializer : IPofSerializer
{
public void Serialize(IPofWriter pofWriter, object o)
{
var c = (Customer) o;
pofWriter.WriteString(0, c.getName());
pofWriter.WriteObject(1, c.getProduct());
pofWriter.WriteRemainder(null);
}
public object Deserialize(IPofReader pofReader)
{
String name = pofReader.ReadString(0);
var customer = new Customer(name);
pofReader.RegisterIdentity(customer);
customer.setProduct((Product) pofReader.ReadObject(1));
pofReader.ReadRemainder();
return customer;
}
}
IPofSerializer
インタフェースの実装であるPofAnnotationSerializer
クラスを使用してシリアライズまたはデシリアライズします。注釈は、IPortableObject
およびIPofSerializer
インタフェースのかわりに使用でき、オブジェクトをシリアライズ可能にするために必要な時間やコードの量を削減します。この項には次のトピックが含まれます:
クラスとクラスのプロパティがPOFシリアライズ可能であることを示すために利用できる注釈は2つあります。
[Portable
] - クラスをPOFシリアライズ可能とマークします。注釈は、クラス・レベルのみに使用でき、メンバーを含みません。
[PortableProperty
] - プロパティ、アクセッサまたはメンバー変数をPOFシリアライズ化されたプロパティとしてマークします。注釈が付けられたメソッドは、アクセッサの表記法(Get
、Set
、Is
)に従っている必要があります。メンバーを、POF索引や、シリアライズまたはデシリアライズの前後で実行するカスタム・コーデックの指定に使用できます。索引の値は省略可能で、自動的に割り当てられます。カスタム・コーデックを入力しない場合は、デフォルトのコーデックが使用されます。
次の例は、クラス、プロパティおよびメンバー変数への注釈付けを示しています。さらに、PortableProperty
索引が明示的に指定されています。
[Portable] public class Person { [PortableProperty(0)] public string GetFirstName() { return m_firstName; } private String m_firstName; [PortableProperty(1)] public string LastName; { get; set; } [PortableProperty(2)] private int m_age; }
POF注釈付きオブジェクトは、pof-config.xml
ファイルの<user-type
要素内で登録する必要があります。『Oracle Coherenceでのアプリケーションの開発』のPOFユーザー定義型の構成要素に関する項を参照してください。POF注釈付きオブジェクトは、IPortableObject
を実装していない場合はPofAnnotationSerializer
シリアライザを使用し、Portable
として注釈が付けられます。ただし、このシリアライザは、オブジェクトが注釈付きかどうかと、ユーザー定義型に含める必要がないことを自動的に仮定します。次の例では、注釈付きPerson
オブジェクトのユーザー定義型を登録します。
<?xml version='1.0'?> <pof-config xmlns="http://schemas.tangosol.com/pof"> <user-type-list> <!-- include all "standard" Coherence POF user types --> <include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml <!-- User types must be above 1000 --> <user-type> <type-id>1001</type-id> <class-name>My.Examples.Person, MyAssembly</class-name> </user-type> </user-type-list> </pof-config>
POF注釈では、自動索引付けがサポートされており、明示的な索引値の割当てや管理の必要性を軽減されます。[PortableProperty]
注釈を定義している場合は、索引値を省略します。索引の割当てはプロパティ名によって決定されます。明示的に索引値を割り当てるプロパティによって、自動索引値が割り当てられることはありません。次の表は、自動索引アルゴリズムの命令セマンティクスを示しています。自動索引付けは、明示的に定義された索引を維持し(プロパティc
参照)、索引が省略されている場合は、索引を割り当てます。
名前 | 明示的な索引 | 決定された索引 |
---|---|---|
c |
1 |
1 |
a |
omitted |
0 |
b |
omitted |
2 |
注意:
自動索引では、現在、進化可能なクラスがサポートされていません。
自動索引付けを有効にするには、POF構成ファイルでユーザー定義型としてオブジェクトを登録するときにPofAnnotationSerializer
シリアライザ・クラスを明示的に定義する必要があります。コンストラクタ内のautoIndex
ブール・パラメータで自動索引を有効にでき、必ずtrue
に設定します。次に例を示します。
<user-type>
<type-id>1001</type-id>
<class-name>Examples.Person</class-name>
<serializer>
<class-name>Tangosol.IO.Pof.PofAnnotationSerializer, Coherence</class-name>
<init-params>
<init-param>
<param-type>int</param-type>
<param-value>{type-id}</param-value>
</init-param>
<init-param>
<param-type>class</param-type>
<param-value>{class}</param-value>
</init-param>
<init-param>
<param-type>bool</param-type>
<param-value>true</param-value>
</init-param>
</init-params>
</serializer>
</user-type>
コーデックによって、シリアライズまたはデシリアライズの前後でコードを実行できます。コーデックでは、IPofWriter
およびIPofReader
インタフェースを使用して、移植可能なプロパティをエンコードおよびデコードする方法を定義できます。コーデックは、一般に、デシリアライズ中に消失する可能性がある実用的な実装に使用します。または、オブジェクトをシリアライズする前にIPofWriter
インタフェースで特定のメソッドを明示的にコールするために使用します。
コーデックを作成するには、ICodec
インタフェースを実装するクラスを作成します。次の例は、リンクされたリスト型の実用的な実装を定義するコーデックを示しています。
public class LinkedListCodec<T> : ICodec { public object Decode(IPofReader reader, int index) { return reader.ReadCollection(index, (ICollection)new LinkedList<T>()); } public void Encode(IPofWriter writer, int index, object value) { writer.WriteCollection(index, (ICollection)value); } }
コーデックをプロパティに割り当てるには、コーデックを[PortableProperty]
属性のメンバーとして入力します。コーデックを指定しない場合は、デフォルトのコーデック(DefaultCodec
)が使用されます。次の例は、前述のLinkedListCodec
コーデックの割当て方法を示しています。
[PortableProperty(typeof(LinkedListCodec<string>))]