---
title:  IPdxSerializable Examples
---

<!--
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.
-->

The native client release contains examples showing how a client application
can register for serialization of domain objects using the .NET IPdxSerializable interface.

The examples are located in `examples\dotnet\pdxserializable`.

The examples define the serializable class, `Orders`, including its serialization and deserialization methods and its factory method.
Once these pieces are in place, execution is simple: the main routine of the example registers the serializable class then performs some put and get operations.

<a id="pdxsbl_execution"></a>
## Execution

The example performs a sequence of operations, displaying simple log entries as they run.

- To run an example, follow the instructions in the README.md file in the example directory.
- Review the source code in the example directory to see exactly how it operates.

- Begin by running a script that sets up the server-side environment by invoking `gfsh` commands to create a region, a locator, and a server.

- Run the example client application, which performs the following steps:

  - Connects to the server
  - Registers the PdxSerializable class
  - Creates orders
  - Stores orders
  - Retrieves orders


<a id="pdsxbl_dotnet_example"></a>
## .NET Example

This section contains code snippets showing highlights of the .NET PdxSerializable example. They are not intended for cut-and-paste execution.
For the complete source, see the example source directory.

The .NET example defines a PdxSerializable class called `Order` that inherits from the `IPdxSerializable` interface.
An `Order` object contains three fields:

- an integer `order_id`
- a string `name`
- a short-int `quantity`

From Order.cs:

```csharp
  public class Order : IPdxSerializable
  {
    ...
    public long OrderId { get; set; }
    public string Name { get; set; }
    public short Quantity { get; set; }
```

Using the `IPdxSerializable` read and write methods, the `Order` class defines `ToData()` and `FromData()`
methods that perform the serialization and deserialization operations, respectively, and the `CreateDeserializable()` factory method:

From Order.cs:

```csharp
    public void ToData(IPdxWriter output)
    {
      output.WriteLong(ORDER_ID_KEY_, OrderId);
      output.MarkIdentityField(ORDER_ID_KEY_);

      output.WriteString(NAME_KEY_, Name);
      output.MarkIdentityField(NAME_KEY_);

      output.WriteInt(QUANTITY_KEY_, Quantity);
      output.MarkIdentityField(QUANTITY_KEY_);
    }

    public void FromData(IPdxReader input)
    {
      OrderId = input.ReadLong(ORDER_ID_KEY_);
      Name = input.ReadString(NAME_KEY_);
      Quantity = (short)input.ReadInt(QUANTITY_KEY_);
    }

    public static IPdxSerializable CreateDeserializable()
    {
      return new Order();
    }
```

The .NET example mainline creates a cache, then uses it to register the PdxSerializable class that was created in Orders.cs:

```csharp
   var cacheFactory = new CacheFactory()
       .Set("log-level", "none");
   var cache = cacheFactory.Create();

   cache.TypeRegistry.RegisterPdxType(Order.CreateDeserializable);
```

The client creates a connection pool and a region named "example_orderobject":

```csharp
   var poolFactory = cache.GetPoolFactory()
       .AddLocator("localhost", 10334);
   poolFactory.Create("pool");

   var regionFactory = cache.CreateRegionFactory(RegionShortcut.PROXY)
        .SetPoolName("pool");
   var orderRegion = regionFactory.Create<int, Order>("example_orderobject");
```

After declaring some keys and values, the client then stores and retrieves an `Order` object:

```csharp
    const int orderKey = 65;

    var order = new Order(orderKey, "Donuts", 12);

    Console.WriteLine("order to put is " + order);
    orderRegion.Put(orderKey, order, null);

    Console.WriteLine("Successfully put order, getting now...");
    var orderRetrieved = orderRegion.Get(orderKey, null);

    Console.WriteLine("Order key: " + orderKey + " = " + orderRetrieved);
```

Finally, the application closes the cache:

```csharp
    cache.Close();
```
