Esempio n. 1
0
            private void WriteAttributeDefinitions(string forNode, Type nodeType)
            {
                foreach (KeyValuePair <PropertyInfo, string> kv in SerializationHelper.GetAttributeProperties(nodeType))
                {
                    //<key id="d1" for="edge" attr.name="weight" attr.type="double"/>
                    this.Writer.WriteStartElement("key");
                    this.Writer.WriteAttributeString("id", kv.Value);
                    this.Writer.WriteAttributeString("for", forNode);
                    this.Writer.WriteAttributeString("attr.name", kv.Value);

                    Type propertyType = kv.Key.PropertyType;
                    if (propertyType == typeof(bool))
                    {
                        this.Writer.WriteAttributeString("attr.type", "boolean");
                    }
                    else if (propertyType == typeof(int))
                    {
                        this.Writer.WriteAttributeString("attr.type", "int");
                    }
                    else if (propertyType == typeof(long))
                    {
                        this.Writer.WriteAttributeString("attr.type", "long");
                    }
                    else if (propertyType == typeof(float))
                    {
                        this.Writer.WriteAttributeString("attr.type", "float");
                    }
                    else if (propertyType == typeof(double))
                    {
                        this.Writer.WriteAttributeString("attr.type", "double");
                    }
                    else
                    {
                        this.Writer.WriteAttributeString("attr.type", "string");
                    }
                    this.Writer.WriteEndElement();
                }
            }
            public static Delegate CreateReadDelegate(
                Type delegateType,
                Type elementType
                //,params string[] ignoredAttributes
                )
            {
                Contract.Requires(delegateType != null);
                Contract.Requires(elementType != null);

                var method = new DynamicMethod(
                    "Read" + elementType.Name,
                    typeof(void),
                    //          reader, namespaceUri
                    new Type[] { typeof(XmlReader), typeof(string), elementType },
                    elementType.Module
                    );
                var gen = method.GetILGenerator();

                var key = gen.DeclareLocal(typeof(string));

                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldstr, "key");
                gen.EmitCall(OpCodes.Callvirt, Metadata.GetAttributeMethod, null);
                gen.Emit(OpCodes.Stloc_0);

                //// if (String.Equals(key, "id")) continue;
                //foreach (string ignoredAttribute in ignoredAttributes)
                //{
                //    gen.Emit(OpCodes.Ldloc_0);
                //    gen.Emit(OpCodes.Ldstr, ignoredAttribute);
                //    gen.EmitCall(OpCodes.Call, Metadata.StringEqualsMethod, null);
                //    gen.Emit(OpCodes.Brtrue, doWhile);
                //}

                // we need to create the swicth for each property
                var  next    = gen.DefineLabel();
                var  @return = gen.DefineLabel();
                bool first   = true;

                foreach (var kv in SerializationHelper.GetAttributeProperties(elementType))
                {
                    var property = kv.Property;

                    if (!first)
                    {
                        gen.MarkLabel(next);
                        next = gen.DefineLabel();
                    }
                    first = false;

                    // if (!key.Equals("foo"))
                    gen.Emit(OpCodes.Ldloc_0);
                    gen.Emit(OpCodes.Ldstr, kv.Name);
                    gen.EmitCall(OpCodes.Call, Metadata.StringEqualsMethod, null);
                    // if false jump to next
                    gen.Emit(OpCodes.Brfalse, next);

                    // do our stuff
                    MethodInfo readMethod = null;
                    if (!Metadata.TryGetReadContentMethod(property.PropertyType, out readMethod))
                    {
                        throw new ArgumentException(String.Format("Property {0} has a non-supported type", property.Name));
                    }

                    // do we have a set method ?
                    var setMethod = property.GetSetMethod();
                    if (setMethod == null)
                    {
                        throw new ArgumentException(String.Format("Property {0}.{1} has not set method", property.DeclaringType, property.Name));
                    }
                    // reader.ReadXXX
                    gen.Emit(OpCodes.Ldarg_2); // element
                    gen.Emit(OpCodes.Ldarg_0); // reader
                    gen.Emit(OpCodes.Ldstr, "data");
                    gen.Emit(OpCodes.Ldarg_1); // namespace uri
                    gen.EmitCall(OpCodes.Callvirt, readMethod, null);
                    gen.EmitCall(OpCodes.Callvirt, setMethod, null);

                    // jump to do while
                    gen.Emit(OpCodes.Br, @return);
                }

                // we don't know this parameter.. we throw
                gen.MarkLabel(next);
                gen.Emit(OpCodes.Ldloc_0);
                gen.Emit(OpCodes.Newobj, Metadata.ArgumentExceptionCtor);
                gen.Emit(OpCodes.Throw);

                gen.MarkLabel(@return);
                gen.Emit(OpCodes.Ret);

                //let's bake the method
                return(method.CreateDelegate(delegateType));
            }
            public static Delegate CreateSetDefaultDelegate(
                Type delegateType,
                Type elementType
                )
            {
                Contract.Requires(delegateType != null);
                Contract.Requires(elementType != null);

                var method = new DynamicMethod(
                    "Set" + elementType.Name + "Default",
                    typeof(void),
                    new Type[] { elementType },
                    elementType.Module
                    );
                var gen = method.GetILGenerator();

                // we need to create the swicth for each property
                foreach (var kv in SerializationHelper.GetAttributeProperties(elementType))
                {
                    var property = kv.Property;
                    var defaultValueAttribute = Attribute.GetCustomAttribute(property, typeof(DefaultValueAttribute))
                                                as DefaultValueAttribute;
                    if (defaultValueAttribute == null)
                    {
                        continue;
                    }
                    var setMethod = property.GetSetMethod();
                    if (setMethod == null)
                    {
                        throw new InvalidOperationException("property " + property.Name + " is not settable");
                    }
                    var value = defaultValueAttribute.Value;
                    if (value != null &&
                        value.GetType() != property.PropertyType)
                    {
                        throw new InvalidOperationException("invalid default value type of property " + property.Name);
                    }
                    gen.Emit(OpCodes.Ldarg_0);
                    switch (Type.GetTypeCode(property.PropertyType))
                    {
                    case TypeCode.Int32:
                        gen.Emit(OpCodes.Ldc_I4, (int)value);
                        break;

                    case TypeCode.Int64:
                        gen.Emit(OpCodes.Ldc_I8, (long)value);
                        break;

                    case TypeCode.Single:
                        gen.Emit(OpCodes.Ldc_R4, (float)value);
                        break;

                    case TypeCode.Double:
                        gen.Emit(OpCodes.Ldc_R8, (double)value);
                        break;

                    case TypeCode.String:
                        gen.Emit(OpCodes.Ldstr, (string)value);
                        break;

                    case TypeCode.Boolean:
                        gen.Emit((bool)value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
                        break;

                    default:
                        throw new InvalidOperationException("unsupported type " + property.PropertyType);
                    }
                    gen.EmitCall(setMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, setMethod, null);
                }
                gen.Emit(OpCodes.Ret);

                //let's bake the method
                return(method.CreateDelegate(delegateType));
            }
Esempio n. 4
0
            private void WriteAttributeDefinitions(string forNode, Type nodeType)
            {
                Contract.Requires(forNode != null);
                Contract.Requires(nodeType != null);

                foreach (var kv in SerializationHelper.GetAttributeProperties(nodeType))
                {
                    var  property     = kv.Property;
                    var  name         = kv.Name;
                    Type propertyType = property.PropertyType;

                    {
                        //<key id="d1" for="edge" attr.name="weight" attr.type="double"/>
                        this.Writer.WriteStartElement("key", GraphMLXmlResolver.GraphMLNamespace);
                        this.Writer.WriteAttributeString("id", name);
                        this.Writer.WriteAttributeString("for", forNode);
                        this.Writer.WriteAttributeString("attr.name", name);

                        string typeCodeStr;

                        try
                        {
                            typeCodeStr = ConstructTypeCode(propertyType);
                        }
                        catch (NotSupportedException)
                        {
                            throw new NotSupportedException(String.Format("Property type {0}.{1} not supported by the GraphML schema", property.DeclaringType, property.Name));
                        }

                        this.Writer.WriteAttributeString("attr.type", typeCodeStr);
                    }

                    // <default>...</default>
                    object defaultValue;
                    if (kv.TryGetDefaultValue(out defaultValue))
                    {
                        this.Writer.WriteStartElement("default");
                        var defaultValueType = defaultValue.GetType();
                        switch (Type.GetTypeCode(defaultValueType))
                        {
                        case TypeCode.Boolean:
                            this.Writer.WriteString(XmlConvert.ToString((bool)defaultValue));
                            break;

                        case TypeCode.Int32:
                            this.Writer.WriteString(XmlConvert.ToString((int)defaultValue));
                            break;

                        case TypeCode.Int64:
                            this.Writer.WriteString(XmlConvert.ToString((long)defaultValue));
                            break;

                        case TypeCode.Single:
                            this.Writer.WriteString(XmlConvert.ToString((float)defaultValue));
                            break;

                        case TypeCode.Double:
                            this.Writer.WriteString(XmlConvert.ToString((double)defaultValue));
                            break;

                        case TypeCode.String:
                            this.Writer.WriteString((string)defaultValue);
                            break;

                        case TypeCode.Object:
                            if (defaultValueType.IsArray)
                            {
                                throw new NotImplementedException("Default values for array types are not implemented");
                            }
                            throw new NotSupportedException(String.Format("Property type {0}.{1} not supported by the GraphML schema", property.DeclaringType, property.Name));

                        default:
                            throw new NotSupportedException(String.Format("Property type {0}.{1} not supported by the GraphML schema", property.DeclaringType, property.Name));
                        }
                        this.Writer.WriteEndElement();
                    }

                    this.Writer.WriteEndElement();
                }
            }
Esempio n. 5
0
            public static Delegate CreateWriteDelegate(Type nodeType, Type delegateType)
            {
                Contract.Requires(nodeType != null);
                Contract.Requires(delegateType != null);

                var method = new DynamicMethod(
                    "Write" + delegateType.Name + nodeType.Name,
                    typeof(void),
                    new Type[] { typeof(XmlWriter), nodeType },
                    nodeType.Module
                    );
                var   gen      = method.GetILGenerator();
                Label @default = default(Label);

                foreach (var kv in SerializationHelper.GetAttributeProperties(nodeType))
                {
                    var property = kv.Property;
                    var name     = kv.Name;

                    var getMethod = property.GetGetMethod();
                    if (getMethod == null)
                    {
                        throw new NotSupportedException(String.Format("Property {0}.{1} has not getter", property.DeclaringType, property.Name));
                    }
                    MethodInfo writeValueMethod;
                    if (!Metadata.TryGetWriteValueMethod(property.PropertyType, out writeValueMethod))
                    {
                        throw new NotSupportedException(String.Format("Property {0}.{1} type is not supported", property.DeclaringType, property.Name));
                    }

                    var defaultValueAttribute =
                        Attribute.GetCustomAttribute(property, typeof(DefaultValueAttribute))
                        as DefaultValueAttribute;
                    if (defaultValueAttribute != null)
                    {
                        @default = gen.DefineLabel();
                        var value = defaultValueAttribute.Value;
                        if (value != null &&
                            value.GetType() != property.PropertyType)
                        {
                            throw new InvalidOperationException("inconsistent default value of property " + property.Name);
                        }

                        switch (Type.GetTypeCode(property.PropertyType))
                        {
                        case TypeCode.Int32:
                            gen.Emit(OpCodes.Ldc_I4, (int)value);
                            break;

                        case TypeCode.Int64:
                            gen.Emit(OpCodes.Ldc_I8, (long)value);
                            break;

                        case TypeCode.Single:
                            gen.Emit(OpCodes.Ldc_R4, (float)value);
                            break;

                        case TypeCode.Double:
                            gen.Emit(OpCodes.Ldc_R8, (double)value);
                            break;

                        case TypeCode.String:
                            gen.Emit(OpCodes.Ldstr, (string)value);
                            break;

                        case TypeCode.Boolean:
                            gen.Emit((bool)value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
                            break;

                        default:
                            throw new InvalidOperationException("unsupported type " + property.PropertyType);
                        }
                        gen.Emit(OpCodes.Ldarg_1);
                        gen.EmitCall(OpCodes.Callvirt, getMethod, null);
                        gen.Emit(OpCodes.Ceq);
                        gen.Emit(OpCodes.Brtrue, @default);
                    }

                    // for each property of the type,
                    // write it to the xmlwriter (we need to take care of value types, etc...)
                    // writer.WriteStartElement("data")
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.Emit(OpCodes.Ldstr, "data");
                    gen.Emit(OpCodes.Ldstr, GraphMLXmlResolver.GraphMLNamespace);
                    gen.EmitCall(OpCodes.Callvirt, Metadata.WriteStartElementMethod, null);

                    // writer.WriteStartAttribute("key");
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.Emit(OpCodes.Ldstr, "key");
                    gen.Emit(OpCodes.Ldstr, name);
                    gen.EmitCall(OpCodes.Callvirt, Metadata.WriteAttributeStringMethod, null);

                    // writer.WriteValue(v.xxx);
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.Emit(OpCodes.Ldarg_1);
                    gen.EmitCall(OpCodes.Callvirt, getMethod, null);
                    // When reading scalar values we call member methods of XmlReader, while for array values
                    // we call our own static methods.  These two types of methods seem to need different opcode.
                    var opcode = writeValueMethod.DeclaringType == typeof(XmlWriterExtensions) ? OpCodes.Call : OpCodes.Callvirt;
                    gen.EmitCall(opcode, writeValueMethod, null);

                    // writer.WriteEndElement()
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.EmitCall(OpCodes.Callvirt, Metadata.WriteEndElementMethod, null);

                    if (defaultValueAttribute != null)
                    {
                        gen.MarkLabel(@default);
                        @default = default(Label);
                    }
                }

                gen.Emit(OpCodes.Ret);

                //let's bake the method
                return(method.CreateDelegate(delegateType));
            }
Esempio n. 6
0
            public static Delegate CreateReadDelegate(
                Type delegateType,
                Type elementType,
                params string[] ignoredAttributes
                )
            {
                DynamicMethod method = new DynamicMethod(
                    "Read" + elementType.Name,
                    typeof(void),
                    new Type[] { typeof(XmlReader), elementType },
                    elementType.Module
                    );
                ILGenerator gen = method.GetILGenerator();

                MethodInfo readToFollowing =
                    typeof(XmlReader).GetMethod(
                        "ReadToFollowing",
                        BindingFlags.Instance | BindingFlags.Public,
                        null,
                        new Type[] { typeof(string) },
                        null);
                MethodInfo getAttribute =
                    typeof(XmlReader).GetMethod(
                        "GetAttribute",
                        BindingFlags.Instance | BindingFlags.Public,
                        null,
                        new Type[] { typeof(string) },
                        null);
                MethodInfo stringEquals =
                    typeof(string).GetMethod(
                        "op_Equality",
                        BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public,
                        null,
                        new Type[] { typeof(string), typeof(string) },
                        null);
                ConstructorInfo argumentException =
                    typeof(ArgumentException).GetConstructor(new Type[] { });


                // read content as methods
                Dictionary <Type, MethodInfo> readContentMethods = new Dictionary <Type, MethodInfo>();

                readContentMethods.Add(typeof(int), typeof(XmlReader).GetMethod("ReadElementContentAsInt", new Type[] { }));
                readContentMethods.Add(typeof(double), typeof(XmlReader).GetMethod("ReadElementContentAsDouble", new Type[] { }));
                readContentMethods.Add(typeof(bool), typeof(XmlReader).GetMethod("ReadElementContentAsBoolean", new Type[] { }));
                readContentMethods.Add(typeof(DateTime), typeof(XmlReader).GetMethod("ReadElementContentAsDateTime", new Type[] { }));
                readContentMethods.Add(typeof(long), typeof(XmlReader).GetMethod("ReadElementContentAsLong", new Type[] { }));
                readContentMethods.Add(typeof(string), typeof(XmlReader).GetMethod("ReadElementContentAsString", new Type[] { }));


                LocalBuilder key = gen.DeclareLocal(typeof(string));

                Label start   = gen.DefineLabel();
                Label doWhile = gen.DefineLabel();

                gen.Emit(OpCodes.Br_S, doWhile);
                gen.MarkLabel(start);
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldstr, "key");
                gen.EmitCall(OpCodes.Callvirt, getAttribute, null);
                gen.Emit(OpCodes.Stloc_0);


                // if (key.Equals("id")) continue;
                foreach (string ignoredAttribute in ignoredAttributes)
                {
                    gen.Emit(OpCodes.Ldloc_0);
                    gen.Emit(OpCodes.Ldstr, ignoredAttribute);
                    gen.EmitCall(OpCodes.Call, stringEquals, null);
                    gen.Emit(OpCodes.Brtrue_S, doWhile);
                }

                // we need to create the swicth for each property
                Label next  = gen.DefineLabel();
                bool  first = true;

                foreach (KeyValuePair <PropertyInfo, string> kv in SerializationHelper.GetAttributeProperties(elementType))
                {
                    if (!first)
                    {
                        gen.MarkLabel(next);
                        next = gen.DefineLabel();
                    }
                    first = false;

                    // if (!key.Equals("foo"))
                    gen.Emit(OpCodes.Ldloc_0);
                    gen.Emit(OpCodes.Ldstr, kv.Value);
                    gen.EmitCall(OpCodes.Callvirt, stringEquals, null);
                    // if false jump to next
                    gen.Emit(OpCodes.Brfalse_S, next);

                    // do our stuff
                    MethodInfo readMethod = null;
                    if (!readContentMethods.TryGetValue(kv.Key.PropertyType, out readMethod))
                    {
                        throw new ArgumentException(String.Format("Property {0} has a non-supported type", kv.Key.Name));
                    }

                    // do we have a set method ?
                    MethodInfo setMethod = kv.Key.GetSetMethod();
                    if (setMethod == null)
                    {
                        throw new ArgumentException(
                                  String.Format("Property {0} is readonly", kv.Key.Name)
                                  );
                    }
                    // reader.ReadXXX
                    gen.Emit(OpCodes.Ldarg_1);
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.EmitCall(OpCodes.Callvirt, readMethod, null);
                    gen.EmitCall(OpCodes.Callvirt, setMethod, null);

                    // jump to do while
                    gen.Emit(OpCodes.Br_S, doWhile);
                }

                // we don't know this parameter.. we throw
                gen.MarkLabel(next);
                gen.Emit(OpCodes.Newobj, argumentException);
                gen.Emit(OpCodes.Throw);

                gen.MarkLabel(doWhile);
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldstr, "data");
                gen.EmitCall(OpCodes.Callvirt, readToFollowing, null);
                gen.Emit(OpCodes.Brtrue_S, start);

                gen.Emit(OpCodes.Ret);

                //let's bake the method
                return(method.CreateDelegate(delegateType));
            }
Esempio n. 7
0
            public static Delegate CreateWriteDelegate(Type nodeType, Type delegateType)
            {
                DynamicMethod method = new DynamicMethod(
                    "Write" + delegateType.Name + nodeType.Name,
                    typeof(void),
                    new Type[] { typeof(XmlWriter), nodeType },
                    nodeType.Module
                    );
                ILGenerator gen = method.GetILGenerator();

                MethodInfo writeStartElement =
                    typeof(XmlWriter).GetMethod(
                        "WriteStartElement",
                        BindingFlags.Instance | BindingFlags.Public,
                        null,
                        new Type[] { typeof(string) },
                        null);
                MethodInfo writeEndElement =
                    typeof(XmlWriter).GetMethod(
                        "WriteEndElement",
                        BindingFlags.Instance | BindingFlags.Public,
                        null,
                        new Type[] { },
                        null);
                MethodInfo writeString =
                    typeof(XmlWriter).GetMethod(
                        "WriteString",
                        BindingFlags.Instance | BindingFlags.Public,
                        null,
                        new Type[] { typeof(string) },
                        null);
                MethodInfo writeAttributeString =
                    typeof(XmlWriter).GetMethod(
                        "WriteAttributeString",
                        BindingFlags.Instance | BindingFlags.Public,
                        null,
                        new Type[] { typeof(string), typeof(string) },
                        null);
                MethodInfo toString = typeof(object).GetMethod(
                    "ToString",
                    BindingFlags.Public | BindingFlags.Instance,
                    null,
                    new Type[] { },
                    null);

                foreach (KeyValuePair <PropertyInfo, string> kv in SerializationHelper.GetAttributeProperties(nodeType))
                {
                    // for each property of the type,
                    // write it to the xmlwriter (we need to take care of value types, etc...)
                    // writer.WriteStartElement("data")
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.Emit(OpCodes.Ldstr, "data");
                    gen.EmitCall(OpCodes.Callvirt, writeStartElement, null);

                    // writer.WriteAttributeString("key", name);
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.Emit(OpCodes.Ldstr, "key");
                    gen.Emit(OpCodes.Ldstr, kv.Value);
                    gen.EmitCall(OpCodes.Callvirt, writeAttributeString, null);


                    // writer.WriteString(v.xxx);
                    gen.Emit(OpCodes.Ldarg_0);

                    // we now need to load the vertex and invoke the property
                    // load vertex
                    gen.Emit(OpCodes.Ldarg_1);
                    // invoke property
                    MethodInfo getMethod = kv.Key.GetGetMethod();
                    gen.EmitCall(
                        (getMethod.IsVirtual) ? OpCodes.Callvirt : OpCodes.Call,
                        getMethod,
                        null);

                    // since XmlWrite takes to string, we need to convert that
                    // object to a string...
                    // of course, if it's a string, we don't need to do anything
                    Type propertyType = kv.Key.PropertyType;
                    if (propertyType != typeof(string))
                    {
                        // if it's a value type, it has to be boxed before
                        // invoking ToString
                        if (propertyType.IsValueType)
                        {
                            gen.Emit(OpCodes.Box, propertyType);
                        }
                        gen.Emit(
                            (toString.IsVirtual) ? OpCodes.Callvirt : OpCodes.Call,
                            toString);
                    }

                    // we now have two string on the stack...
                    gen.EmitCall(OpCodes.Callvirt, writeString, null);

                    // writer.WriteEndElement()
                    gen.Emit(OpCodes.Ldarg_0);
                    gen.EmitCall(OpCodes.Callvirt, writeEndElement, null);
                }

                gen.Emit(OpCodes.Ret);

                //let's bake the method
                return(method.CreateDelegate(delegateType));
            }