From ac136fe40fd94e324efdae874cb2350bd20715ec Mon Sep 17 00:00:00 2001 From: xinchen Date: Sun, 18 Sep 2016 20:30:19 -0700 Subject: [PATCH] Articles update --- amqp-vs2013.sln | 1 + amqp.sln | 1 + docs/articles/installation.md | 43 +++++++++++++ docs/articles/serialization.md | 106 +++++++++++++++++++++++++++------ docs/articles/toc.yml | 2 + docs/articles/versioning.md | 5 +- 6 files changed, 135 insertions(+), 23 deletions(-) create mode 100644 docs/articles/installation.md diff --git a/amqp-vs2013.sln b/amqp-vs2013.sln index cf76da7..e6592e5 100644 --- a/amqp-vs2013.sln +++ b/amqp-vs2013.sln @@ -147,6 +147,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "articles", "articles", "{D9 docs\articles\contributing.md = docs\articles\contributing.md docs\articles\device_to_iothub.md = docs\articles\device_to_iothub.md docs\articles\hello_amqp.md = docs\articles\hello_amqp.md + docs\articles\installation.md = docs\articles\installation.md docs\articles\listener.md = docs\articles\listener.md docs\articles\serialization.md = docs\articles\serialization.md docs\articles\service_to_iothub.md = docs\articles\service_to_iothub.md diff --git a/amqp.sln b/amqp.sln index 97521e2..6d95fbd 100644 --- a/amqp.sln +++ b/amqp.sln @@ -108,6 +108,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "articles", "articles", "{56 docs\articles\contributing.md = docs\articles\contributing.md docs\articles\device_to_iothub.md = docs\articles\device_to_iothub.md docs\articles\hello_amqp.md = docs\articles\hello_amqp.md + docs\articles\installation.md = docs\articles\installation.md docs\articles\listener.md = docs\articles\listener.md docs\articles\serialization.md = docs\articles\serialization.md docs\articles\service_to_iothub.md = docs\articles\service_to_iothub.md diff --git a/docs/articles/installation.md b/docs/articles/installation.md new file mode 100644 index 0000000..c495f38 --- /dev/null +++ b/docs/articles/installation.md @@ -0,0 +1,43 @@ +The library is installed to the application projects through the NuGet packages. + +## NuGet Packages + +The following NuGet packages are available. + +* __AMQPNetLite__ - the package containing the targets of all supported platforms. +* __AMQPNetMicro__ - the package containing a compact version for NETMF. To reduce +storage and memory footprints, this version has its own APIs and implementation +that are specifically designed for memory and space constrained devices. +* .Net Core packages - the packages for any netstandard1.3 compliant platforms. + * __AMQPNetLite.Core__ - the core protocol implementation and the client/listener +APIs. + * __AMQPNetLite.Serialization__ - the AMQP Serializer that serializes custom +types using the standard AMQP type system. + * __AMQPNetLite.WebSockets__ - the WebSocket transport for the client. + +## Installation + +To reference the library, install the corresponding NuGet package into the +projects you are developing. + +### Visual Studio + +Open Manage NuGet Packages window. Search for the package mentioned above for +the platform of your application. Install the package. + +Alternatively, open Package Manager Console and execute the following command. +``` +Install-Package AmqpNetLite -ProjectName YourProjectName +``` + +### .Net Core cli + +If you develop with other editors and build with the cli tool chain, add the +following to your project.json file. + +``` + "dependencies": { + "AMQPNetLite.Core": "2.0.0", + "Other.Dependency": "1.0.0" + } +``` \ No newline at end of file diff --git a/docs/articles/serialization.md b/docs/articles/serialization.md index 8c5cd4f..cb197d4 100644 --- a/docs/articles/serialization.md +++ b/docs/articles/serialization.md @@ -1,12 +1,18 @@ -# Serialization - -AMQP defines a type system for primitive types and custom types. The serializer converts any serializable .NET object into AMQP bytes, and vice visa. Since the payload contains a complete valid sequence of AMQP values, it becomes easy for the application to send .NET objects across the network, and also interoperate with any other AMQP compliant clients that can read/write AMQP values. +AMQP defines a type system for primitive types and custom types. The serializer converts +any serializable .NET object into AMQP bytes, and vice visa. Since the payload contains +a complete valid sequence of AMQP values, it becomes easy for the application to send +.NET objects across the network, and also interoperate with any other AMQP compliant +clients that can read/write AMQP values. ## Serializable Types + The following types are serializable. * Primitives -* Custom Types - User defined classes are encoded as AMQP described types when the class and its fields/properties are annotated with the AMQP serialization attributes. See [AmqpContract](#amqpcontract) for details. -* [IAmqpSerializable](#iamqpserializable) - User defined classes that implement this interface can be serialized using the Encode and Decode implementation provided by the user. +* Custom Types - User defined classes are encoded as AMQP described types when the class +and its fields/properties are annotated with the AMQP serialization attributes. +See [AmqpContract](#amqpcontract) for details. +* [IAmqpSerializable](#iamqpserializable) - User defined classes that implement this +interface can be serialized using the Encode and Decode implementation provided by the user. The mapping between .NET and AMQP primitive types is defined in the following table. @@ -38,11 +44,14 @@ The mapping between .NET and AMQP primitive types is defined in the following ta * decimal is not supported ## AmqpContract + A user defined class can be annotated with a few attribute classes to be serializable. ### Example + ``` namespace Amqp.Examples; + [AmqpContract] class Person { @@ -68,7 +77,10 @@ class Person } } ``` -With these annotations, the class is serialized as an AMQP described list. The descriptor name is the class's full name. The following is the equivalent xml definition. + +With these annotations, the class is serialized as an AMQP described list. The descriptor +name is the class's full name. The following is the equivalent xml definition. + ``` @@ -79,22 +91,44 @@ With these annotations, the class is serialized as an AMQP described list. The d ``` ### AmqpContractAttribute -A class annotated with this attribute is serializable. The attribute specifies the descriptor name and code, and also the AMQP type to contain the fields/properties. + +A class annotated with this attribute is serializable. The attribute specifies the descriptor +name and code, and also the AMQP type to contain the fields/properties. + ``` [AmqpContract(Name = "amqp.examples:person", Code = 0x0000123400000000, Encoding = EncodingType.Map)] ``` -By default, the descriptor name is the class full name. If descriptor code is provided, the name is ignored. The descriptor is scoped to the instance of AmqpSerializer that performs the serialization. The static methods of AmqpSerializer belong to the default static instance. Application SHOULD ensure that the descriptor is unique in the serialization scope to avoid conflicts. -When Encoding is set to SimpleList or SimpleMap, the descriptor is not serialized. The object is encoded directly as an AMQP list or map. + +By default, the descriptor name is the class full name. If descriptor code is provided, the name +is ignored. The descriptor is scoped to the instance of AmqpSerializer that performs the serialization. +The static methods of AmqpSerializer belong to the default static instance. Application SHOULD ensure +that the descriptor is unique in the serialization scope to avoid conflicts. +When Encoding is set to SimpleList or SimpleMap, the descriptor is not serialized. The object is +encoded directly as an AMQP list or map. ### AmqpMemberAttribute + This attribute specifies that a field or a property should be included in serialization. + ``` [AmqpMember(Name = "name", Order = 0)] ``` -The Name property defines the member name, and the Order property defines the position of the member in all members. For list type of encoding, Name is not used, and Order is used to sort the members to decide the final position of each member in the list. Order does not need to contiguous, but must be unique. For map type of encoding, Order is not used, and Name is used as the key of the item in the map. EncodingType.Map encodes the key as AMQP symbol and decodes both symbol and string keys. EncodingType.SimpleMap encodes keys as strings. + +The Name property defines the member name, and the Order property defines the position of the member +in all members. For list type of encoding, Name is not used, and Order is used to sort the members +to decide the final position of each member in the list. Order does not need to contiguous, but must +be unique. For map type of encoding, Order is not used, and Name is used as the key of the item in +the map. EncodingType.Map encodes the key as AMQP symbol and decodes both symbol and string keys. +EncodingType.SimpleMap encodes keys as strings. ### AmqpProvidesAttribute -This attribute is used by the decoder to resolve types based on the given type and the descriptor in the payload. After the descriptor is read from the payload, it is compared to the descriptors of the known types and the matching one is chosen. This attribute can only be used for encoding type List or Map because descriptors are required in serialization. A common scenario is class inheritance. The base and derived classes must have the same EncodingType. + +This attribute is used by the decoder to resolve types based on the given type and the descriptor in +the payload. After the descriptor is read from the payload, it is compared to the descriptors of +the known types and the matching one is chosen. This attribute can only be used for encoding type +List or Map because descriptors are required in serialization. A common scenario is class inheritance. +The base and derived classes must have the same EncodingType. + ``` [AmqpContract] class Student : Person @@ -117,13 +151,23 @@ class Person { } ``` + Student and Teacher are now known types of Person, so it is possible to deserialize objects by calling. + ``` var person = AmqpSerializer.Deserialize(ByteBuffer); ``` -If the payload contains Student, Teacher, or Person objects, the concrete object will be returned and referenced by person variable. -This attribute can also be used just as a type resolver without class inheritance. In this case, the generic argument type is only a registry for knowns types. Since the generic argument type is not the base class of its known types, the serializer will fail to cast the decoded object to the generic argument type. This issue can be resolved by calling the `AmqpSerializer.Deserialize(ByteBuffer)` method, where T is the registry type and TAs is the base type of all decoded objects. Let’s assume we have another class Address which is not related to Person and its derived classes. +If the payload contains Student, Teacher, or Person objects, the concrete object will be returned +and referenced by person variable. + +This attribute can also be used just as a type resolver without class inheritance. In this case, +the generic argument type is only a registry for knowns types. Since the generic argument type is not +the base class of its known types, the serializer will fail to cast the decoded object to the generic +argument type. This issue can be resolved by calling the `AmqpSerializer.Deserialize(ByteBuffer)` +method, where T is the registry type and TAs is the base type of all decoded objects. Let’s assume we +have another class Address which is not related to Person and its derived classes. + ``` [AmqpContract] class Address @@ -141,31 +185,55 @@ class Resolver { } ``` -In addition to Person objects, if the buffer could also contain Address objects, using Person as deserialization type will fail. With the Resolver class, we can decode all objects by calling `AmqpSerializer.Deserialize(ByteBuffer)`. + +In addition to Person objects, if the buffer could also contain Address objects, using Person as +deserialization type will fail. With the Resolver class, we can decode all objects by calling +`AmqpSerializer.Deserialize(ByteBuffer)`. Note that Student and Teacher should be added even when Person is added. ### Serialization Callbacks -Extra logic can be inserted before and after serialization/deserialization by serialization callbacks. The callback methods should be annotated with the system runtime serialization attributes. + +Extra logic can be inserted before and after serialization/deserialization by serialization callbacks. +The callback methods should be annotated with the system runtime serialization attributes. * [OnSerializingAttribute](https://msdn.microsoft.com/en-us/library/system.runtime.serialization.onserializingattribute(v=vs.110).aspx) - invoked before writing members * [OnSerializedAttribute](https://msdn.microsoft.com/en-us/library/system.runtime.serialization.onserializedattribute(v=vs.110).aspx) - invoked after writing members * [OnDeserializingAttribute](https://msdn.microsoft.com/en-us/library/system.runtime.serialization.ondeserializingattribute(v=vs.110).aspx) - invoked before reading members * [OnDeserializedAttribute](https://msdn.microsoft.com/en-us/library/system.runtime.serialization.ondeserializedattribute(v=vs.110).aspx) - invoked after reading members ## IAmqpSerializable -The interface enables the application to have full control on how a type should be serialized by implementing Encode and Decode methods. + +The interface enables the application to have full control on how a type should be serialized by +implementing Encode and Decode methods. ## Message Integration -The library provides a seamless integration of the serializer and the messaging layer. When a message is created from a serializable object, the object is automatically serialized in the AMQP Value body. When a message is received, the object can be read by calling `Message.GetBody()`. + +The library provides a seamless integration of the serializer and the messaging layer. When a message +is created from a serializable object, the object is automatically serialized in the AMQP Value body. +When a message is received, the object can be read by calling `Message.GetBody()`. + ``` // sending an object in a message -var Student = new Student() { Name = "Bob" }; +var student = new Student() { Name = "Bob" }; sender.Send(new Message(student)); // reading an object from a message var message = receiver.Receive(); var person = message.GetBody(); ``` + Here are some benefits you will get. * Serialization is completely transparent. The application works with strongly typed objects. -* No need of another serializer to handle message body. It minimizes dependency of your application, and very likely improves the performance. +* No need of another serializer to handle message body. It minimizes dependency of your application, +and very likely improves the performance. * It is standard and open. Any client that supports the AMQP type system is able to produce and consume the data. + +On .Net Core (netstandard1.3), the serializer is in a seperate package (AMQPNetLite.Serialization). +To use this feature, you should do the following. +* Install the serialization package. +* When creating a message for send, use the `AmqpValue` class to wrap the object of your custom type. +``` +var student = new Student() { Name = "Bob" }; +var message = new Message() { BodySection = new AmqpValue(student) }; +sender.Send(message); +``` +* Use the same way to read the object by calling `Message.GetBody()`. \ No newline at end of file diff --git a/docs/articles/toc.yml b/docs/articles/toc.yml index 906dce1..641f91f 100644 --- a/docs/articles/toc.yml +++ b/docs/articles/toc.yml @@ -8,6 +8,8 @@ href: working_with_code.md - name: Using the Library items: + - name: NuGet Packages + href: installation.md - name: Versioning href: versioning.md - name: Serialization diff --git a/docs/articles/versioning.md b/docs/articles/versioning.md index 34468a1..57b421d 100644 --- a/docs/articles/versioning.md +++ b/docs/articles/versioning.md @@ -1,9 +1,6 @@ The library uses the following versioning scheme for the assemblies and the NuGet packages. `..` -So for example, the version at the time this was written was: -`1.2.0` - ## Assembly Version ``` @@ -15,7 +12,7 @@ patch - typically do not change. Assemblies in the package are signed with a published key, so they are strongly named. `major` and `minor` version numbers are increased as shown above. When a new release does not have any breaking changes, assembly version remains the same. This enables the application to do -an in-place upgrade without recompiling or updating the app. +an in-place upgrade without recompiling or updating the application code. ## Assembly File Version