| <% set_title("Using the", product_name, "PDX Autoserializer") %> |
| |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| It's extremely easy for .NET applications to store and retrieve data from Geode. All that's required |
| is a single line of code to set the `PdxSerializer` to the .NET client's `ReflectionBasedAutoSerializer`: |
| |
| ```csharp |
| cache.TypeRegistry.PdxSerializer = new ReflectionBasedAutoSerializer(); |
| ``` |
| |
| (The autoserializer can be registered only in the application code. It cannot be configured declaratively in `cache.xml`.) |
| |
| After an autoserializer has been registered, all user classes can automatically be stored without needing to implement any |
| interfaces. For example, the following `put` command stores `value`, which is an instance of a user defined class, in |
| the region. |
| |
| ```csharp |
| region.put(key, value); |
| ``` |
| |
| The .NET client's `ReflectionBasedAutoSerializer` supports the full list of .NET primitives and other common |
| built-in types. |
| |
| Types without a no-arg constructor are not supported by the `ReflectionBasedAutoSerializer`. This |
| includes all user defined structs. `System.Data.Datatable` is an example of a system class that is not |
| supported due to lack of a no-arg constructor. |
| |
| ## <a id="auto-ser-java-interop"></a>Java Interoperability with .NET Specific Types |
| |
| Java does not have unsigned data types or exact equivalents of `Guid` and `Decimal`. Care should be |
| taken when passing these types between .NET and Java applications using the .NET |
| `ReflectionBasedAutoSerializer`. For example, if storing `UInt16` data (that is, 16-bit unsigned values), |
| be aware that values greater than `UInt16.MaxValue/2 - 1` will show up as negative numbers in |
| Java. Using that data in a Java application may have unexpected behavior. If you expect to exceed |
| half the range for the given type (`Byte.MaxValue/2`, `UInt16.MaxValue/2`, `UInt32.MaxValue/2`, or |
| `UInt64.MaxValue/2`) you should use the next larger type. This obviously breaks down for |
| `UInt64`, which has no next larger type. However, if your range exceeds `UIn64.MaxValue/2`, you likely |
| have a much more complex set of issues to deal with, such as heavy paging due to such a large data |
| set. |
| |
| ## <a id="auto-ser-remote-queries"></a>Remote Queries of .NET Only Types |
| |
| At this time the .NET Client does not support queries against user classes that have been stored on |
| the server using the `ReflectionBasedAutoSerializer`. |
| |
| When you register the reflection-based serializer, <%=vars.product_name%> uses it to serialize all |
| objects that do not implement `IPdxSerializable`. You can customize the |
| auto-serialization behavior for your domain objects by adding serialization attributes to your |
| object’s fields. |
| |
| ## <a id='pdx-ser-extending-auto'></a>Extending the PDX Autoserializer |
| |
| For each object you intend to have autoserialized, you can customize the serialization as needed. |
| |
| **Note:** If you also use PDX serialization in Java for the object, customize your serialization in the same way for both languages. |
| |
| The following extension methods apply to autoserialization: |
| |
| - **WriteTransform**. Controls what field value is written during auto serialization. |
| - **ReadTransform**. Controls what field value is read during auto deserialization. |
| - **GetFieldType**. Defines the specific field names that will be generated during autoserialization. |
| - **IsIdentityField**. Controls which field is marked as the identity field. Identity fields are used when a `PdxInstance` computes its hash code to determine whether it is equal to another object. |
| - **GetFieldType**. Determines the field type that will be used when autoserializing the given field. |
| - **IsFieldIncluded**. Specifies which fields of a class to autoserialize. |
| |
| To specify an identifier field in your domain object, add the attribute `PdxIdentityField` to the field. |
| |
| For example: |
| |
| ```csharp |
| [PdxIdentityField] private int id; |
| ``` |
| |
| To exclude a field from serialization, add the .NET attribute `NonSerialized` to the field. |
| |
| For example: |
| |
| ```csharp |
| [NonSerialized] private int myLocalData; |
| ``` |
| |
| For each domain class <%=vars.product_name%> serializes using the autoserializer, all fields are |
| considered for serialization except those defined as `static`, `literal` or `readonly` and those you |
| explicitly exclude using the .NET `NonSerialized` attribute. |
| |
| This example code demonstrates how to extend the autoserializer to customize serialization. |
| |
| ```csharp |
| public class AutoSerializerEx : ReflectionBasedAutoSerializer |
| { |
| public override object WriteTransform(FieldInfo fi, Type type, object originalValue) { |
| if (fi.FieldType.Equals(Type.GetType("System.Guid"))) { |
| return originalValue.ToString(); |
| } else if (fi.FieldType.Equals(Type.GetType("System.Decimal"))) { |
| return originalValue.ToString(); |
| } else |
| return base.WriteTransform(fi, type, originalValue); |
| } |
| |
| public override object ReadTransform(FieldInfo fi, Type type, object serializeValue) { |
| if (fi.FieldType.Equals(Type.GetType("System.Guid"))) { |
| Guid g = new Guid((string)serializeValue); |
| return g; |
| } else if (fi.FieldType.Equals(Type.GetType("System.Decimal"))) { |
| return Convert.ToDecimal((string)serializeValue); |
| } else |
| return base.ReadTransform(fi, type, serializeValue); |
| } |
| |
| public override FieldType GetFieldType(FieldInfo fi, Type type) { |
| if (fi.FieldType.Equals(Type.GetType("System.Guid")) || |
| fi.FieldType.Equals(Type.GetType("System.Decimal"))) |
| return FieldType.STRING; |
| return base.GetFieldType(fi, type); |
| } |
| |
| public override bool IsIdentityField(FieldInfo fi, Type type) { |
| if (fi.Name == "_identityField") |
| return true; |
| return base.IsIdentityField(fi, type); |
| } |
| |
| public override string GetFieldName(FieldInfo fi, Type type) { |
| if (fi.Name == "_nameChange") |
| return fi.Name + "NewName"; |
| return fi.Name; |
| } |
| |
| public override bool IsFieldIncluded(FieldInfo fi, Type type) |
| { |
| if (fi.Name == "_notInclude") |
| return false; |
| return base.IsFieldIncluded(fi, type); |
| } |
| } |
| ``` |
| |
| |