EQXSerializer(Type type)
        {
            m_type = type;
            m_dynamicType = DynamicType.GetDynamicType(m_type);

            // build the functions here to pay the cost up front, once per type, instead of at runtime
            //  whenever an element is processed
            ReaderDelegate readAttributes = (XPathNavigator reader, ref object target) => { };
            ReaderDelegate readElements = (XPathNavigator reader, ref object target) => { };
            ReaderDelegate readArrays = (XPathNavigator reader, ref object target) => { };
            WriterDelegate writeAttributes = (XElement result, ref object target) => { };
            WriterDelegate writeElements = (XElement result, ref object target) => { };
            WriterDelegate writeArrays = (XElement result, ref object target) => { };
            for (int i = 0; i < m_dynamicType.Members.Count; i++)
            {
                // this goofy setup is to prevent the dynamic methods from acessing the wrong member
                int temp = i;
                DynamicMember member = m_dynamicType.Members[temp];

                object[] attributes = member.MemberInfo.GetCustomAttributes(false);
                EqXAttributeAttribute eqxAttribute = null;
                EqXElementAttribute eqxElement = null;
                EqXArrayAttribute eqxArray = null;
                DefaultValueAttribute defaultValue = null;
                foreach (object attr in attributes)
                {
                    eqxAttribute = eqxAttribute ?? attr as EqXAttributeAttribute;
                    eqxElement = eqxElement ?? attr as EqXElementAttribute;
                    eqxArray = eqxArray ?? attr as EqXArrayAttribute;
                    defaultValue = defaultValue ?? attr as DefaultValueAttribute;
                }

                // count how many of the eqx attributes are present
                int eqxCount = ((eqxAttribute != null) ? 1 : 0) + ((eqxElement != null) ? 1 : 0) + ((eqxArray != null) ? 1 : 0);
            #if DEBUG
                // check how many attributes are present in debug builds to sort out ambiguity
                if (eqxCount > 1)
                    Trace.TraceWarning(TooManyAttributes, m_type.Name, member.MemberName);
            #endif
                // don't process members that aren't marked
                if (eqxCount < 1) continue;

            #if DEBUG
                if (!member.CanWrite && !member.CanRead)
                {
                    Trace.TraceWarning("'{0}.{1}' has no way to be read or written, skipping it.", m_type.Name, member.MemberName);
                    continue;
                }
                else if (!member.CanRead)
                {
                    Trace.TraceWarning("'{0}.{1}' marked for serialization but can not be read, skipping it.", m_type.Name, member.MemberName);
                    continue;
                }
                else if (!member.CanWrite)
                {
                    Trace.TraceWarning("'{0}.{1}' marked for serialization but can not be written, skipping it.", m_type.Name, member.MemberName);
                    continue;
                }
            #endif
                // find the default value for the member
                object dvalue = null;
                if (defaultValue != null)
                    dvalue = defaultValue.Value;
                if (member.MemberType.IsValueType && dvalue == null)
                    dvalue = Activator.CreateInstance(member.MemberType);

                if (eqxAttribute != null)
                {
                    if (!member.MemberType.IsPrimitive && member.MemberType != typeof(string))
                        throw new InvalidOperationException(string.Format(OnlyPrimitivesXmlAttributes, m_type.Name, member.MemberName));

                    string name = eqxAttribute.Name ?? member.MemberName;
                    readAttributes += ReadPrimitive(member, string.Concat("@", name), dvalue);
                    writeAttributes += WritePrimitiveAttribute(member, name, dvalue, eqxAttribute.AlwaysWrite);
                }
                else if (eqxElement != null)
                {
                    string name = eqxElement.Name ?? member.MemberName;
                    if (member.MemberType.IsComplex() && member.MemberType != typeof(string))
                    {
                        readElements += ReadComplex(member, name, dvalue);
                        writeElements += WriteComplexElement(member, name, dvalue, eqxElement.AlwaysWrite);
                    }
                    else
                    {
                        readElements += ReadPrimitive(member, name, dvalue);
                        writeElements += WritePrimitiveElement(member, name, dvalue, eqxElement.AlwaysWrite);
                    }
                }
                else if (eqxArray != null)
                {
                    string name = eqxArray.Name ?? member.MemberName;
                    readElements += ReadArray(member, name, eqxArray.ItemName, dvalue);
                    writeElements += WriteArray(member, name, eqxArray.ItemName, dvalue, eqxArray.AlwaysWrite);
                }
            }

            m_reader = (XPathNavigator navigator, ref object target) =>
            {
                if (target == null)
                    target = m_dynamicType.CreateInstance();

                if (navigator.HasAttributes)
                    readAttributes(navigator, ref target);

                if (navigator.HasChildren)
                {
                    readElements(navigator, ref target);
                    readArrays(navigator, ref target);
                }
            };

            m_writer = (XElement result, ref object target) =>
            {
                if (target != null)
                {
                    writeAttributes(result, ref target);
                    writeElements(result, ref target);
                    writeArrays(result, ref target);
                }
            };
        }