How to make a class that can be added to the Windows.Foundation.Collections.ValueSet

3

I am making a UWP application that utilizes an AppServiceConnection to send data to a COM style application. The AppServiceConnection.SendMessageAsync() takes a type of Windows.Foundation.Collections.ValueSet

The ValueSet class is a collection, similar to a dictionary that stores KeyValuePairs of types <string, object>

I am having trouble adding data to the ValueSet, and every time I attempt to add an object I receive the error: "Data of this type is not supported. (Exception from HRESULT: 0x8007065E)"

research on this error reveals that the object to be added must be of a serializable type, and can implement Windows.Foundation.Collections.IPropertySet which is in of itself a collection interface that seems to store keyvaluepairs.

I would like to know how to make a class that can be added to a ValueSet. Do I have to create a new collection implementing IPropertySet or is there some way to make the class itself serializable and able to be added to the ValueSet?

If I have to implement IPropertySet can anyone point me to decent documentation on how to do this?

c#
uwp
asked on Stack Overflow Sep 22, 2017 by Mason Turvey • edited Sep 22, 2017 by Mason Turvey

1 Answer

3

WinRT has no notion of serializable objects; it only supports value types like integers, bools, strings, arrays, date-times, etc. and collections of those things. Look at the static Create* members of the PropertyValue class for examples (although you are not required to use those methods to create the items you put into the set).

If you want to serialize a WinRT object or your own .NET object, you can turn it onto JSON or XML and then put that into the ValueSet.

For example:

  public void TestValueSet()
  {
    var x = new ValueSet();

    // Integers are OK
    x.Add("a", 42);

    // URIs are not OK - can't be serialized
    try
    {
      x.Add("b", new Uri("http://bing.com"));
    }
    catch (Exception ex)
    {
      Debug.WriteLine("Can't serialize a URI - " + ex.Message);
    }

    // Custom classes are not OK
    var myClass = new MyClass { X = 42, Y = "hello" };
    try
    {
      x.Add("c", myClass);
    }
    catch (Exception ex)
    {
      Debug.WriteLine("Can't serialize custom class - " + ex.Message);
    }

    // Serialized classes are OK
    x.Add("d", Serialize<MyClass>(myClass));

    foreach (var kp in x)
    {
      Debug.WriteLine("{0} -> {1}", kp.Key, kp.Value);
    }
  }

  string Serialize<T>(T value)
  {
    var dcs = new DataContractSerializer(typeof(T));
    var stream = new MemoryStream();
    dcs.WriteObject(stream, value);
    stream.Position = 0;
    var buffer = new byte[stream.Length];
    stream.Read(buffer, 0, (int)stream.Length);
    return Encoding.UTF8.GetString(buffer);
  }
}

[DataContract]
public class MyClass
{
  [DataMember]
  public int X { get; set; }
  [DataMember]
  public string Y { get; set; }
}
answered on Stack Overflow Sep 24, 2017 by Peter Torr - MSFT

User contributions licensed under CC BY-SA 3.0