public void serializeWithType(Object o, Class type, SerializationContext sc, SerializationStateImpl state) {
        
        // recurse with superclass before processing
        Class supertype = type.getSuperclass();
        if (supertype != Object.class) {
            serializeWithType(o, supertype, sc, state);
        }
        
        BitTable bt = (BitTable)type.getAnnotation(BitTable.class);
        if (bt == null) {
            return;
        }
        
        List<InstanceLifecycleListener> instanceListeners = getAttachedListeners(o, type, InstanceLifecycleListener.class);
        List<PropertyLifecycleListener> propertyListeners = getAttachedListeners(o, type, PropertyLifecycleListener.class);
        
        // event
        for (InstanceLifecycleListener listener : instanceListeners) {
            listener.preSerializeInstance(o, state);
        }
        
        state.setPropertyQueue(new LinkedList<>(Arrays.asList(bt.propOrder())));
        
        while (!state.getPropertyQueue().isEmpty()) {
            
            String name = state.getPropertyQueue().remove(0);
            
            AbstractPropertyAccessor accessor = getAccessor(type, name);
            
            // event
            boolean skipProperty = false;
            for (PropertyLifecycleListener listener : propertyListeners) {
                skipProperty |= !listener.preSerializeProperty(o, accessor, state);
                if (skipProperty)
                    break;
            }
            if (skipProperty)
                continue;
            
            long bitPosition = sc.getBuffer().getBitPosition();

            Object fieldValue = accessor.getValue(o);
            SerializationContext subContext = new PropertyBackedSerializationContext(accessor.annotatedElement, sc.getBuffer(), accessor.type, sc.getRootSerializer());
            try {
                sc.getRootSerializer().serialize(fieldValue, subContext);
            } catch (Exception e) {
                throw new RuntimeException("Unable to serialize filed [" + type.getName() + "#" + name + "].", e);
            }
            
            long bitLength = sc.getBuffer().getBitPosition() - bitPosition;

            state.getBufferLayout().add(new SerializationStateImpl.PropertyLayoutImpl(name, bitPosition, bitLength));
            
            // event
            for (PropertyLifecycleListener listener : propertyListeners) {
                listener.postSerializeProperty(o, accessor, state);
            }
        }
        
        /*
        // event
        for (InstanceLifecycleListener listener : instanceListeners) {
            listener.postSerializeInstance(o, state);
        }
        */
        
    }