Esempio n. 1
0
        /// <summary>
        /// Default key serializer
        /// </summary>
        byte[] IBigtableKeySerializer <object> .SerializeKey(object instance, Encoding encoding)
        {
            // Contract
            if (instance == null)
            {
                throw new InvalidOperationException("Can not serialize keys on a null reference.");
            }

            // Locals
            //bool missingKey = false;
            var bytes     = new List <byte[]>();
            var separator = encoding.GetBytes(KeyFieldSeparator);

            // Iterate keys
            for (int index = 0; index < KeyFields.Length; index++)
            {
                // Localize
                var fieldName = KeyFields[index];
                var required  = RequiredFields.Contains(fieldName);
                var value     = Getters[fieldName](instance);

                //
                if (value == null)
                {
                    if (required)
                    {
                        throw new SerializationException(String.Format("The member {0} on type {1} is marked as required but was not specified", FieldNameLookup[fieldName], _type));
                    }
                    bytes.Add(separator);
                    //missingKey = true;
                    continue;
                }
                //if (missingKey)
                //{
                //    // Programmer exception
                //    var exception = new MissingFieldException(_type.Name, memberName);
                //    // User exception // TODO: I think I designed around this
                //    throw new SerializationException("The default serializer insists that the primary keys are filled in order.  Missing keys are okay as long as all subsequent keys are missing as well.", exception);
                //}
                var valueType  = value.GetType();
                var serializer = GetSerializerForType(valueType);

                if (IsBigBoxed[fieldName])
                {
                    if (!IsSpecified[fieldName](instance))
                    {
                        bytes.Add(new byte[0]);
                        continue;
                    }
                    //var fieldType = MemberTypes[memberName];
                    //var access = GetKeyAccess(fieldType);
                    //value = access.ValueGetter(value);
                }
                var serialized = serializer.SerializeField(valueType, value, TableEncoding);
                bytes.Add(serialized);
            }
            var bytesSize = bytes.Count - 1;
            var sepLength = (bytesSize) * separator.Length;
            var results   = new byte[sepLength + bytes.Sum(b => b.Length)];
            var ptr       = 0;

            for (int index = 0; index < bytes.Count; index++)
            {
                // Get field bytes
                var source = bytes[index];

                // Copy to result array in correct position
                Array.Copy(source, 0, results, ptr, source.Length);

                // Move ptr forward
                ptr += source.Length;
                if (index < bytesSize)
                {
                    // Copy in separator
                    Array.Copy(separator, 0, results, ptr, sepLength);

                    // Move ptr foward
                    ptr += sepLength;
                }
            }

            // Tada!
            return(results);
        }
Esempio n. 2
0
        private bool ExtractAccessors(MemberInfo member, string fieldName, ref Type dataType, ref bool isKey)
        {
            // Locals
            var getter = default(FieldGetterDelegate);
            var setter = default(FieldSetterDelegate);

            // Homogenize fields and properties
            switch (member.MemberType)
            {
            case System.Reflection.MemberTypes.Field:
                var field = ((FieldInfo)member);
                dataType = field.FieldType;
                getter   = field.GetValue;
                setter   = field.SetValue;
                break;

            case System.Reflection.MemberTypes.Property:
                var property = ((PropertyInfo)member);
                dataType = property.PropertyType;
                getter   = property.GetValue;
                setter   = property.SetValue;
                break;

            default:
                // Ignore other member types
                return(false);
            }

            // Inspect fields for key, specifiable/actual data type
            var bigtableKey = member.GetCustomAttribute <BigTableKeyAttribute>();
            var genDataType = dataType.IsGenericType ? dataType.GetGenericTypeDefinition() : null;
            var isBigField  = genDataType == typeof(BigTableField <>);
            var isBigKey    = genDataType == typeof(BigTableKey <>);

            isKey = bigtableKey != null || genDataType == typeof(BigTableKey <>);
            var isBigWrapper = isBigField || isBigKey;

            IsBigBoxed.Add(fieldName, isBigWrapper);

            // Store accessors
            if (isBigWrapper)
            {
                var subDataType = dataType.GenericTypeArguments[0];
                var access      = isKey ? (BigAccess)GetKeyAccess(subDataType) : GetFieldAccess(subDataType);
                IsSpecified.Add(fieldName, target => ((IBigTableField)getter(target)).IsSpecified);
                Getters.Add(fieldName, target => access.ValueGetter(getter(target)));
                var useDataType = dataType;
                Setters.Add(fieldName, (target, value) =>
                {
                    var newValue = Activator.CreateInstance(useDataType);

                    access.ValueSetter(newValue, value);
                    setter(target, newValue);
                });

                dataType = subDataType;
            }
            else
            {
                IsSpecified.Add(fieldName, target => true);
                Getters.Add(fieldName, getter);
                Setters.Add(fieldName, setter);
            }

            // Indicate is property of field
            return(true);
        }