コード例 #1
0
        public ValueContext(Type valueType)
        {
            Type       = valueType;
            Properties = new Dictionary <string, PropertyInfo>();

            if (valueType != typeof(string) && typeof(IList).IsAssignableFrom(valueType))
            {
                // Find the type our collection contains, which we'll use this to create instances of any Structs in this collection
                if (valueType.IsGenericType)
                {
                    // If generic collection, what's our T?
                    CollectedType = valueType.GetGenericArguments().FirstOrDefault();

                    // Hope that this is a generic collection of some kind
                    Value = Activator.CreateInstance(valueType);
                }
                else if (valueType.IsArray)
                {
                    // If array, what's our T[]?
                    CollectedType = valueType.GetElementType();

                    // We treat arrays differently, because they're ILists but they throw when .Add() is called
                    // We'll back this array with a List<T> and call .ToArray() later
                    Value = Activator.CreateInstance(typeof(List <>).MakeGenericType(CollectedType));
                }
                else
                {
                    throw new ArgumentException($"{valueType} must be an IList that is either an array or generic collection", nameof(valueType));
                }
            }
            else
            {
                // Find our public properties
                foreach (PropertyInfo property in valueType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                {
                    if (property.GetCustomAttribute <XmlRpcIgnoreAttribute>() != null)
                    {
                        continue;
                    }

                    XmlRpcMemberAttribute xmlRpcMember = property.GetCustomAttribute <XmlRpcMemberAttribute>();

                    if (xmlRpcMember != null)
                    {
                        Properties.Add(xmlRpcMember.Name, property);
                    }
                    else
                    {
                        Properties.Add(property.Name, property);
                    }
                }

                Value = Activator.CreateInstance(valueType);
            }
        }
コード例 #2
0
        public static async Task WriteXmlRpcObjectAsync(this XmlWriter writer, object target)
        {
            if (target == null)
            {
                return;
            }

            // Built-In Types Table (C# Reference)
            // https://msdn.microsoft.com/en-us/library/ya5y69ds.aspx
            if (target is bool)
            {
                // Convert booleans to "1" or "0"
                writer.WriteXmlRpcValue("boolean", (bool)target ? "1" : "0");
            }
            else if (target is byte)
            {
                // Unsigned
                throw new ArgumentException("target is byte, use sbyte instead", nameof(target));
            }
            else if (target is sbyte)
            {
                // Signed 8-bit
                writer.WriteXmlRpcValue("i4", Convert.ToString(Convert.ToInt32(target)));
            }
            else if (target is char)
            {
                // Unicode 16-bit
                writer.WriteXmlRpcValue("string", Convert.ToString(target));
            }
            else if (target is decimal)
            {
                // Data loss, use double
                throw new ArgumentException("target is decimal, conversion to double may result in loss of precision", nameof(target));
            }
            else if (target is double)
            {
                writer.WriteXmlRpcValue("double", Convert.ToString(Convert.ToDouble(target), CultureInfo.InvariantCulture));
            }
            else if (target is float)
            {
                // 32-bit, convert to double
                writer.WriteXmlRpcValue("double", Convert.ToString(Convert.ToDouble(target), CultureInfo.InvariantCulture));
            }
            else if (target is int)
            {
                writer.WriteXmlRpcValue("i4", Convert.ToString(Convert.ToInt32(target)));
            }
            else if (target is uint)
            {
                // Unsigned
                throw new ArgumentException("target is uint, use signed 32-bit integer instead", nameof(target));
            }
            else if (target is long)
            {
                // Signed 64-bit
                throw new ArgumentException("target is long, use signed 32-bit integer instead", nameof(target));
            }
            else if (target is ulong)
            {
                // Unsigned
                throw new ArgumentException("target is ulong, use signed 32-bit integer instead", nameof(target));
            }
            else if (target is short)
            {
                // Signed 16-bit
                writer.WriteXmlRpcValue("i4", Convert.ToString(Convert.ToInt32(target)));
            }
            else if (target is ushort)
            {
                // Unsigned 16-bit
                throw new ArgumentException("target is ushort, use short instead", nameof(target));
            }
            else if (target is string)
            {
                await writer.WriteXmlRpcValueAsync("string", Convert.ToString(target));
            }
            else if (target is DateTime)
            {
                writer.WriteXmlRpcValue("dateTime.iso8601", ((DateTime)target).ToString("yyyyMMdd'T'HH':'mm':'ss", CultureInfo.InvariantCulture));
            }
            else if (target is byte[])
            {
                // Base64
                await writer.WriteXmlRpcValueAsync("base64", Convert.ToBase64String((byte[])target));
            }
            else if (target is IEnumerable)
            {
                writer.WriteStartElement("value");
                writer.WriteStartElement("array");
                writer.WriteStartElement("data");

                foreach (object item in (IEnumerable)target)
                {
                    await writer.WriteXmlRpcObjectAsync(item);
                }

                writer.WriteEndElement();
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
            else
            {
                writer.WriteStartElement("value");
                writer.WriteStartElement("struct");

                foreach (PropertyInfo property in target.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
                {
                    MethodInfo getMethod = property.GetGetMethod();

                    if (getMethod != null && property.GetCustomAttribute <XmlRpcIgnoreAttribute>() == null)
                    {
                        object propertyValue = getMethod.Invoke(target, null);

                        // Don't try to serialize a null value
                        // We won't include this <member> at all
                        if (propertyValue == null)
                        {
                            continue;
                        }

                        writer.WriteStartElement("member");

                        XmlRpcMemberAttribute xmlRpcMember = property.GetCustomAttribute <XmlRpcMemberAttribute>();

                        // In death, a member of Project Struct has a name
                        writer.WriteStartElement("name");
                        writer.WriteString(xmlRpcMember != null ? xmlRpcMember.Name : property.Name);
                        writer.WriteEndElement();

                        await writer.WriteXmlRpcObjectAsync(propertyValue);

                        writer.WriteEndElement();
                    }
                }

                writer.WriteEndElement();
                writer.WriteEndElement();
            }
        }