I have a header file defining some structs I want to use in my code.
public value struct HttpHeader
{
Platform::String^ mName;
Platform::String^ mValue;
};
typedef Platform::Collections::Vector<HttpHeader> HttpHeaders;
public value struct HttpRequestEvent
{
Platform::String^ mUri;
HttpHeaders^ mHeaders;
};
When I build this I get this error:
error C3986: 'mHeaders': signature of public member contains native type 'std::equal_to<_Ty>'
with
[
_Ty=cpcpb::HttpHeader
] (SettingsServiceImpl.cpp)
What am I missing here? Isn't everything I'm using C++/Cx?
Use Windows::Foundation::Collections::IVector instead of Platform::Collections::Vector.
To use Platform::Collections::Vector you have to provide a custom comparator which is the equals operator.
Check this link - http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/5ec2090f-b7e6-40e8-9cd7-75cf36d05ab3/
Related
I'm trying to implement a general serialization framework to convert outgoing and incoming messages to json using the kotlinx serialialization. I'm developing a multiplatform app, so I'm trying to get it to run on KotlinJVM and KotlinJS.
For this, I add a type field to every message and use a map that maps each type string to a KClass. What's the type for that map? It contains KClass<> objects whose classes extend the Message class, therefore in java I'd specify my map as
Map<KClass<? extends Message>, String>.
How can I do that in Kotlin?
Afterwards I need to serialize and deserialize the message based on its key and therefore type. Java frameworks take a Class parameter for the type of the object I want to deserialize/instantiate (e.g. gson.fromJson(ClientMessage.class)). In Kotlin this is done using reified parameters Json.decodeFromString<Type>. I do not know the type of the message at compile time though and just have a reference to a KClass, how can I instantiate an object based on that?
#Serializable
open class Message(val type: String) {
companion object {
val messageTypes: Map<KClass<out Message>, String> = mapOf(
ClientLoginMessage::class to "clientLoginMessage",
Message::class to "message"
)
inline fun <reified T> getMessageTypeByClass(): String = messageTypes[T::class]!! // utility for defining the type in the constructors of the individual messages
}
fun toJson() = Json.encodeToString(this)
fun fromJson(json: String): Message? {
val plainMessage = Json.decodeFromString<Message>(json) // get type string from json
return messageTypes.entries.find { it.value == plainMessage.type }?.let {
// how can I use the KClass from it.key as reified parameter?
Json.decodeFromString<?????>(json)
}
}
}
#Serializable
class ClientLoginMessage
: Message(Message.getMessageTypeByClass<ClientLoginMessage>()) {}
Create a map of serializers like for types:
val serializers: Map<KClass<out Message>, KSerializer<out Message>> = mapOf(
ClientLoginMessage::class to ClientLoginMessage.serializer(),
Message::class to Message.serializer()
)
Pass in the serializer needed to Json.decodeFromString like this:
fun fromJson(json: String): Message? {
val plainMessage = Json.decodeFromString<Message>(json) // get type string from json
return messageTypes.entries.find { it.value == plainMessage.type }?.let {
// how can I use the KClass from it.key as reified parameter?
Json.decodeFromString(serializers.get(plainMessage.type)!!, json)
}
}
You might also want to have a look at the Kotlin built in handling of polymorphic classes: https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/polymorphism.md
I am trying to parse an API response mainly constructured like this:
{
"ApiFunc1":{
"SomeData1":"SomeValue1",
"SomeData2":"SomeValue2",
"SomeData3":"SomeValue3"
}
}
{
"ApiFunc2":{
"SomeData4":"SomeValue4",
"SomeData5":"SomeValue5",
"SomeData6":"SomeValue6"
}
}
.
.
.
I created a base class as follows:
class Model_BaseResponse<TResponse> : Serializable {
#SerializedName("ErrorMessage")
var errorMessage: String? = null
#SerializedName("value")
var data: TResponse? = null
}
Each ApiFunc returns different data. I want to create a base class where data: TResponse's #SerializedName("ApiFunc1") or #SerializedName("ApiFunc2") can be set in child class. Is there any way to that? I do it in regular way, defining the
#SerializedName("value")
var data: TResponse? = null
in every child class. Just been curious about that. Thanks in advance for any idea.
An annotation like SerializedData requires its arguments to be compile-time constants. Having a look at what "compile-time constant" means in Kotlin reveals:
Properties the value of which is known at compile time can be marked as compile time constants using the const modifier. Such properties need to fulfil the following requirements:
Top-level or member of an object
Initialized with a value of type String or a primitive type
No custom getter
Such properties can be used in annotations:
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
#Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }
I believe the first requirement "Top-level or member of an object" cannot be fulfilled for your use case.
I have this JSON:
{
"argument0": {
"argument1": "test",
"argument2": {
"argument3": "test3"
}
}
}
I need to use some kind of recursive struct with methods like the HashMap<String, _> in Rust. The key should always be a String but the value can be a String or the same Argument struct.
#[derive(Clone, RustcDecodable, RustcEncodable)]
struct Argument {
key: String
value: String Or Argument
}
How can I achieve this?
You have a few distinct problems here.
First, you want to be able to define a data type that can be either one type or another type, but not both. This is what Rust's enum data type is intended for.
enum Value {
String(String),
Argument(Argument),
}
This Value type can contain either a String or an Argument, but not both.
Now, we need to define the Argument type. In your example, an argument can contain arbitrary field names, so we can't just define a struct. Instead, we can use a map collection from the standard library to map Strings to Values, such as BTreeMap. We'll also define a type alias so that we can use the name Argument instead of BTreeMap<String, Argument> elsewhere in the program.
use std::collections::BTreeMap;
type Argument = BTreeMap<String, Argument>;
Now that we've successfully defined the type, let's define its serialization behavior using the serde library. Serde can automatically serialize types from the Rust standard library, and user structs can implement or derive the Serialize and Deserialize traits to add the functionality to their own types.
For most structs, we can just add a #[derive(Serialize)] and/or #[derive(Deserialize)] to implement the necessary traits for serialization. In this case, we want to customize the deserialization of our enum to be untagged, so it just emits the value of the enum, not an object with "String" or "Argument" as the key. Instead, we just want the JSON to contain the value. We do this by adding a special attribute to the struct, #[serde(untagged)].
Here's a short Rust program that demonstrates the above concepts. This program will read your JSON example, and print the Debug representation of a Rust type that represents the data.
#[macro_use]
extern crate serde_derive; // 1.0.78
extern crate serde; // 1.0.78
extern crate serde_json; // 1.0.27
use std::collections::BTreeMap;
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
enum Value {
String(String),
Argument(Argument),
}
type Argument = BTreeMap<String, Value>;
fn main() {
let argument: Argument = serde_json::from_str(
r#"{
"argument0": {
"argument1": "test",
"argument2": {
"argument3": "test3"
}
}
}"#,
).unwrap();
println!("{:?}", argument);
}
We have a single contract assembly which has all our data contracts. We are using JSON.net for serializing our data contracts to json.
JSON.Net adds both the type name and the assembly name in the $type attribute on serialization. Since all our data contracts are in the same assembly which is always loaded in the current app domain, we should be able to omit this.
How can we achieve this?
Thanks
You can use the Binder property in your JsonSerializerSettings.
This blog post (by the library author) describes the steps: http://james.newtonking.com/archive/2011/11/19/json-net-4-0-release-4-bug-fixes.aspx
In short, you create a custom class deriving from SerializationBinder and override two methods:
BindToName(Type serializedType, out string assemblyName, out string typeName)
BindToType(string assemblyName, string typeName)
The logic you place in those methods will give you direct control over how type names are converted to string representation in the $type field, and how types are located at run-time given values from $type.
In your case, wanting to omit the Assembly name, you can probably do:
public override void BindToName(
Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = null;
typeName = serializedType.FullName;
}
public override Type BindToType(string assemblyName, string typeName)
{
return Type.GetType(typeName);
}
I think maybe tag the class with the JsonObjectAttribute
[DataContract]
[JsonObject("")]
public class MyContractClass { ... }
This should override the fact that it is also a DataContract.
I have the following simple function:
public class BaseEntityRepository<TEntity, TId> : IBaseEntityRepository<TEntity, TId>
where TEntity : class, TBaseEntity, IIdentifiedEntity<TId>
where TId : struct {
//...
public virtual TEntity GetById(TId id) {
return (from e in GetAll() where e.Id.Equals(id) select e).SingleOrDefault();
}
//...
}
Since TId is a generic I'm receiving the following message:
"Unable to create a constant value of type 'System.Object'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."
No matter what type it represent. I've tried "Byte", "Int16", "Int32", "Long"... The message is the same.
I thought that defining the generic constraint as struct would be enought to the type be reconized as a primitive.
BTW... GetAll() returns an IQueryable<TEntity>.
Anyway... Does anybody know an workaround?
Thanks
How about IEquatable?
where TId : IEquatable<TId>
Just a guess. What if you tried this?
e.Id.GetHashCode() == id.GetHashCode()