Example #1
0
        // ========================================
        // property
        // ========================================

        // ========================================
        // method
        // ========================================
        public void SaveTo(IMemento memento, ExternalizeContext context)
        {
            foreach (var prop in _properties)
            {
                var externalAttr = TypeService.Instance.GetExternalAttribute(prop);
                if (externalAttr == null)
                {
                    continue;
                }

                var value = prop.GetValue(_target, null);
                if (value == null)
                {
                    continue;
                }

                var valueType = value.GetType();
                var propType  = prop.PropertyType;
                var propName  = prop.Name;


                if (GenericTypeUtil.IsGenericIDictionary(propType))
                {
                    var elemTypes             = GenericTypeUtil.GetGenericArgumentOfGenericIDictionary(valueType);
                    var isKeyExternalizable   = IsExternalizable(elemTypes[0]);
                    var isValueExternalizable = IsExternalizable(elemTypes[1]);

                    var dictType      = typeof(IDictionary <,>).MakeGenericType(elemTypes);
                    var getKeysMethod = dictType.GetMethod("get_Keys");
                    var getItemMethod = dictType.GetMethod("get_Item");

                    if (isKeyExternalizable)
                    {
                        if (isValueExternalizable)
                        {
                            var dict = new Dictionary <IMemento, IMemento>();
                            var keys = getKeysMethod.Invoke(value, null) as ICollection;
                            foreach (var key in keys)
                            {
                                var entryValue = getItemMethod.Invoke(value, new[] { key });
                                var keyMem     = context.GetMemento(propName, key);
                                var valMem     = context.GetMemento(propName, entryValue);
                                if (keyMem != null && valMem != null)
                                {
                                    dict.Add(keyMem, valMem);
                                }
                            }
                            memento.WriteSerializable(propName, dict);
                        }
                        else
                        {
                            var dict = new Dictionary <IMemento, object>();
                            var keys = getKeysMethod.Invoke(value, null) as ICollection;
                            foreach (var key in keys)
                            {
                                var entryValue = getItemMethod.Invoke(value, new[] { key });
                                var keyMem     = context.GetMemento(propName, key);
                                if (keyMem != null)
                                {
                                    dict.Add(keyMem, entryValue);
                                }
                            }
                            memento.WriteSerializable(propName, dict);
                        }
                    }
                    else
                    {
                        if (isValueExternalizable)
                        {
                            var dict = new Dictionary <object, IMemento>();
                            var keys = getKeysMethod.Invoke(value, null) as ICollection;
                            foreach (var key in keys)
                            {
                                var entryValue = getItemMethod.Invoke(value, new[] { key });
                                var valMem     = context.GetMemento(propName, entryValue);
                                if (valMem != null)
                                {
                                    dict.Add(key, valMem);
                                }
                            }
                            memento.WriteSerializable(propName, dict);
                        }
                        else
                        {
                            var dict = new Dictionary <object, object>();
                            var keys = getKeysMethod.Invoke(value, null) as ICollection;
                            foreach (var key in keys)
                            {
                                var entryValue = getItemMethod.Invoke(value, new[] { key });
                                dict.Add(key, entryValue);
                            }
                            memento.WriteSerializable(propName, dict);
                        }
                    }
                }
                else if (GenericTypeUtil.IsGenericICollection(propType))
                {
                    var elemType             = GenericTypeUtil.GetGenericArgumentOfGenericICollection(valueType);
                    var isElemExternalizable = IsExternalizable(elemType);

                    if (isElemExternalizable)
                    {
                        var list = new List <IMemento>();
                        foreach (var v in value as IEnumerable)
                        {
                            var elem = context.GetMemento(propName, v);
                            if (elem != null)
                            {
                                list.Add(elem);
                            }
                        }
                        memento.WriteSerializable(propName, list);
                    }
                    else
                    {
                        var list = new List <object>();
                        foreach (var v in value as IEnumerable)
                        {
                            list.Add(v);
                        }
                        memento.WriteSerializable(propName, list);
                    }
                }
                else if (GenericTypeUtil.IsGenericIEnumerable(propType) && externalAttr.Add != null)
                {
                    var elemType             = GenericTypeUtil.GetGenericArgumentOfGenericIEnumerable(valueType);
                    var isElemExternalizable = IsExternalizable(elemType);

                    if (isElemExternalizable)
                    {
                        var list = new List <IMemento>();
                        foreach (var v in value as IEnumerable)
                        {
                            var elem = context.GetMemento(propName, v);
                            if (elem != null)
                            {
                                list.Add(elem);
                            }
                        }
                        memento.WriteSerializable(propName, list);
                    }
                    else
                    {
                        var list = new List <object>();
                        foreach (var v in value as IEnumerable)
                        {
                            list.Add(v);
                        }
                        memento.WriteSerializable(propName, list);
                    }
                }
                else
                {
                    if (valueType.IsPrimitive)
                    {
                        memento.WriteSerializable(propName, value);
                    }
                    else
                    {
                        if (IsExternalizable(valueType))
                        {
                            memento.WriteExternalizable(propName, value);
                        }
                        else
                        {
                            if (externalAttr.Clone == null)
                            {
                                memento.WriteSerializable(propName, value);
                            }
                            else
                            {
                                try {
                                    var flags =
                                        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
                                    var clone  = _type.GetMethod(externalAttr.Clone, flags);
                                    var cloned = clone.Invoke(_target, null);
                                    memento.WriteSerializable(propName, cloned);
                                } catch (Exception e) {
                                    Logger.Error(
                                        string.Format(
                                            "Failed to invoke {0}.{1} for clone",
                                            _type.Name, externalAttr.Clone
                                            ),
                                        e
                                        );
                                    throw;
                                }
                            }
                        }
                    }
                }
            }

            var externalizableAttr = TypeService.Instance.GetExternalizableAttribute(_type);

            if (externalizableAttr.FactoryMethodType != null && externalizableAttr.FactoryMethod != null)
            {
                var factoryMethod = externalizableAttr.FactoryMethodType.GetMethod(
                    externalizableAttr.FactoryMethod,
                    BindingFlags.Public | BindingFlags.Static
                    );
                if (factoryMethod != null)
                {
                    memento.FactoryMethod = factoryMethod;

                    var paras = externalizableAttr.FactoryMethodParamKeys;
                    if (paras != null)
                    {
                        memento.FactoryMethodParamKeys = paras;
                    }
                }
            }

            if (externalizableAttr.ConstructorParamKeys != null)
            {
                memento.ConstructorParamKeys = externalizableAttr.ConstructorParamKeys;
            }

            if (externalizableAttr.Saved != null)
            {
                var saved = _type.GetMethod(externalizableAttr.Saved);
                saved.Invoke(_target, new object[] { memento, context });
            }
        }
Example #2
0
        /// pre: Property start element must be fetched
        /// post: Property end element must be fetched
        protected void LoadProperty(StoreContext context, object target, Type targetType, string propName)
        {
            var reader = context.Reader;
            //var prop = targetType.GetProperty(propName, BindingFlags.Instance | BindingFlags.Public);
            var prop = TypeService.Instance.GetPublicInstanceProperty(targetType, propName);

            if (prop == null)
            {
                /// 無視して現在のプロパティのend elementまで読み進める
                /// reader.Skip()では進みすぎてしまう
                SkipToEndElement(context, reader.Name);
                return;
            }

            var isEntity    = IsEntityDefined(targetType);
            var persistAttr = GetPersistAttribute(prop);

            if (!isEntity || (isEntity && persistAttr != null && persistAttr.Enabled))
            {
                var propType = prop.PropertyType;

                if (propType.IsArray)
                {
                    if (HasPublicSetter(prop))
                    {
                        var elemType = propType.GetElementType();
                        LoadArrayProperty(context, target, prop, elemType);
                    }
                    else
                    {
                        SkipToEndElement(context, reader.Name);
                    }
                }
                else if (GenericTypeUtil.IsGenericIDictionary(propType))
                {
                    if (HasPublicGetter(prop))
                    {
                        var elemTypes = GenericTypeUtil.GetGenericArgumentOfGenericIDictionary(propType);
                        var propValue = GetValue(target, prop);
                        LoadDictionaryProperty(context, propValue, elemTypes);
                    }
                    else
                    {
                        SkipToEndElement(context, reader.Name);
                    }
                }
                else if (GenericTypeUtil.IsGenericICollection(propType))
                {
                    if (HasPublicGetter(prop))
                    {
                        var elemType  = GenericTypeUtil.GetGenericArgumentOfGenericICollection(propType);
                        var propValue = GetValue(target, prop);
                        LoadCollectionProperty(context, target, targetType, prop, propValue, elemType);
                    }
                    else
                    {
                        SkipToEndElement(context, reader.Name);
                    }
                }
                else if (GenericTypeUtil.IsGenericIEnumerable(propType) && persistAttr.Add != null)
                {
                    if (HasPublicGetter(prop))
                    {
                        var elemType  = GenericTypeUtil.GetGenericArgumentOfGenericIEnumerable(propType);
                        var propValue = GetValue(target, prop);
                        LoadEnumerableProperty(context, target, targetType, prop, propValue, elemType);
                    }
                    else
                    {
                        SkipToEndElement(context, reader.Name);
                    }
                }
                else
                {
                    if (HasPublicSetter(prop))
                    {
                        LoadSingletonProperty(context, target, prop, propType);
                    }
                    else
                    {
                        SkipToEndElement(context, reader.Name);
                    }
                }
            }
            else
            {
                SkipToEndElement(context, reader.Name);
            }
        }
Example #3
0
        public void LoadFrom(IMemento memento, ExternalizeContext context)
        {
            var type = _target.GetType();

            foreach (var prop in _properties)
            {
                var externalAttr = TypeService.Instance.GetExternalAttribute(prop);
                if (externalAttr == null)
                {
                    continue;
                }

                var propName = prop.Name;
                var value    = memento.ReadSerializable(propName);
                if (value == null)
                {
                    continue;
                }

                var valueType = value.GetType();
                var propType  = prop.PropertyType;

                if (GenericTypeUtil.IsGenericIDictionary(propType))
                {
                    var elemTypes     = GenericTypeUtil.GetGenericArgumentOfGenericIDictionary(valueType);
                    var dictKeyType   = elemTypes[0];
                    var dictValueType = elemTypes[1];

                    var setItemMethod = propType.GetMethod("set_Item");

                    if (typeof(IMemento).IsAssignableFrom(dictKeyType))
                    {
                        if (typeof(IMemento).IsAssignableFrom(dictValueType))
                        {
                            var dict = memento.ReadSerializable(propName) as IDictionary <IMemento, IMemento>;
                            foreach (var pair in dict)
                            {
                                var keyEx = context.GetExternalizable(propName, pair.Key);
                                var valEx = context.GetExternalizable(propName, pair.Value);
                                if (keyEx != null && valEx != null)
                                {
                                    setItemMethod.Invoke(value, new[] { keyEx, valEx });
                                }
                            }
                        }
                        else
                        {
                            var dict = memento.ReadSerializable(propName) as IDictionary <IMemento, object>;
                            foreach (var pair in dict)
                            {
                                var keyEx = context.GetExternalizable(propName, pair.Key);
                                if (keyEx != null)
                                {
                                    setItemMethod.Invoke(value, new[] { keyEx, pair.Value });
                                }
                            }
                        }
                    }
                    else
                    {
                        if (typeof(IMemento).IsAssignableFrom(dictValueType))
                        {
                            var dict = memento.ReadSerializable(propName) as IDictionary <object, IMemento>;
                            foreach (var pair in dict)
                            {
                                var valEx = context.GetExternalizable(propName, pair.Value);
                                if (valEx != null)
                                {
                                    setItemMethod.Invoke(value, new[] { pair.Key, valEx });
                                }
                            }
                        }
                        else
                        {
                            var dict = memento.ReadSerializable(propName) as IDictionary <object, IMemento>;
                            foreach (var pair in dict)
                            {
                                setItemMethod.Invoke(value, new[] { pair.Key, pair.Value, });
                            }
                        }
                    }
                }
                else if (GenericTypeUtil.IsGenericICollection(propType))
                {
                    var elemType = GenericTypeUtil.GetGenericArgumentOfGenericICollection(valueType);

                    if (typeof(IMemento).IsAssignableFrom(elemType))
                    {
                        var add       = externalAttr.Add;
                        var addMethod = add != null?type.GetMethod(add) : propType.GetMethod("Add");

                        var list            = prop.GetValue(_target, null);
                        var externalizables = memento.ReadExternalizables(propName);
                        foreach (var ex in externalizables)
                        {
                            addMethod.Invoke(list, new[] { ex });
                        }
                    }
                    else
                    {
                        var add       = externalAttr.Add;
                        var addMethod = add != null?type.GetMethod(add) : propType.GetMethod("Add");

                        var list         = prop.GetValue(_target, null);
                        var deserialized = memento.ReadSerializable(propName) as IEnumerable;
                        foreach (var ex in deserialized)
                        {
                            addMethod.Invoke(list, new[] { ex });
                        }
                    }
                }
                else if (GenericTypeUtil.IsGenericIEnumerable(propType) && externalAttr.Add != null)
                {
                    var elemType = GenericTypeUtil.GetGenericArgumentOfGenericIEnumerable(valueType);

                    if (typeof(IMemento).IsAssignableFrom(elemType))
                    {
                        var add             = externalAttr.Add;
                        var addMethod       = type.GetMethod(add);
                        var externalizables = memento.ReadExternalizables(propName);
                        foreach (var ex in externalizables)
                        {
                            addMethod.Invoke(_target, new[] { ex });
                        }
                    }
                    else
                    {
                        var add          = externalAttr.Add;
                        var addMethod    = type.GetMethod(add);
                        var deserialized = memento.ReadSerializable(propName) as IEnumerable;
                        foreach (var ex in deserialized)
                        {
                            addMethod.Invoke(_target, new[] { ex });
                        }
                    }
                }
                else
                {
                    if (valueType.IsPrimitive)
                    {
                        prop.SetValue(_target, memento.ReadSerializable(propName), null);
                    }
                    else
                    {
                        if (typeof(IMemento).IsAssignableFrom(valueType))
                        {
                            prop.SetValue(_target, memento.ReadExternalizable(propName), null);
                        }
                        else
                        {
                            prop.SetValue(_target, memento.ReadSerializable(propName), null);
                        }
                    }
                }
            }

            var externalizableAttr = TypeService.Instance.GetExternalizableAttribute(_type);

            if (externalizableAttr.Loaded != null)
            {
                var loaded = _type.GetMethod(externalizableAttr.Loaded);
                loaded.Invoke(_target, new object[] { memento, context });
            }
        }
Example #4
0
        // ========================================
        // static field
        // ========================================
        public static void ProcessProperty(
            object obj,
            PropertyInfo prop,
            Action <PropertyKind, object> pre,
            Action <PropertyKind, object> post,
            Action <PropertyKind, object, object> each
            )
        {
            var propValue = prop.GetValue(obj, null);

            if (propValue != null)
            {
                var propType    = TypeService.Instance.GetRealType(propValue);
                var persistAttr = TypeService.Instance.GetPersistAttribute(prop);

                if (propType.IsArray)
                {
                    if (HasPublicGetter(prop) && (HasPublicSetter(prop) || persistAttr.Add != null))
                    {
                        ProcessArrayProperty(propValue, propType, pre, post, each);
                    }
                }
                else if (GenericTypeUtil.IsGenericIDictionary(propType))
                {
                    if (HasPublicGetter(prop))
                    {
                        ProcessDictionaryProperty(propValue, propType, pre, post, each);
                    }
                }
                else if (GenericTypeUtil.IsGenericICollection(propType))
                {
                    if (HasPublicGetter(prop))
                    {
                        ProcessEnumerableProperty(propValue, propType, pre, post, each);
                    }
                }
                else if (GenericTypeUtil.IsGenericIEnumerable(propType) && persistAttr.Add != null)
                {
                    if (HasPublicGetter(prop))
                    {
                        ProcessEnumerableProperty(propValue, propType, pre, post, each);
                    }
                }
                else
                {
                    if (HasPublicGetter(prop) && HasPublicSetter(prop))
                    {
                        if (pre != null)
                        {
                            pre(PropertyKind.Single, propValue);
                        }
                        if (each != null)
                        {
                            each(PropertyKind.Single, propValue, null);
                        }
                        if (post != null)
                        {
                            post(PropertyKind.Single, propValue);
                        }
                    }
                }
            }
        }