/// <summary> /// 向 <see cref="IniConfig"/> 维护的 <see cref="IObject"/> 中设置一个对象并序列化成指定节名的 <see cref="ISection"/>, 若节名已存在将会覆盖整个节 /// </summary> /// <param name="sectionKey">用作要添加的元素的键的对象</param> /// <param name="obj">用作要添加的元素的值的对象</param> /// <exception cref="ArgumentException">sectionKey 为空字符串或为 <see langword="null"/></exception> /// <exception cref="ArgumentNullException">obj 为 null</exception> public void SetObject(string sectionKey, object obj) { if (string.IsNullOrEmpty(sectionKey)) { throw new ArgumentException("sectionKey 不允许为空. 原因: obj 不能设置到为未命名的节点", "sectoinKey"); } if (obj == null) { throw new ArgumentNullException("obj"); } if (!this._object.ContainsKey(sectionKey)) // 如果不存在这个名称 { this._object.Add(new ISection(sectionKey)); } // 获取节对象 ISection section = this._object[sectionKey]; if (section.Count > 0) { section.Clear(); } Type tType = obj.GetType(); PropertyInfo[] tProperties = tType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (PropertyInfo property in tProperties) { // 获取属性是否有标记 KeyName IniKeyAttribute keyAttribute = property.GetCustomAttribute <IniKeyAttribute> (); string key = string.Empty; if (keyAttribute != null) { key = keyAttribute.KeyName; } else { key = property.Name; } // 判断 Key 重复 if (section.ContainsKey(key)) { throw new ArgumentException("序列化的对象内部存在一个或多个重复的 Key, 这个异常可能由于属性名和特性引起.", "obj"); } // 获取只有0个参数的 Get 方法 (排除索引器) MethodInfo method = property.GetGetMethod(true); if (method.GetParameters().Count() == 0) { section.Add(key, new IValue(method.Invoke(obj, null))); } } }
/// <summary> /// 从 <see cref="IniConfig"/> 维护的 <see cref="IObject"/> 中获取一个指定节名的 <see cref="ISection"/> 反序列化成指定类型的对象 /// </summary> /// <param name="sectionKey">用作要获取的元素的键的对象</param> /// <param name="t">用作要转换目标对象的类型的对象</param> /// <exception cref="ArgumentNullException">t 为 null</exception> /// <exception cref="ArgumentException">sectionKey 未能匹配到指定节点 或 t 不是 <see cref="RuntimeType"/>。 或 t 是开放式泛型类型(即,<see cref="Type.ContainsGenericParameters"/> 属性将返回 <see langword="true"/>)</exception> /// <exception cref="NotSupportedException">t 不能为 <see cref="TypeBuilder"/>。 或 不支持创建 <see cref="TypedReference"/>、<see cref="ArgIterator"/>、<see cref="Void"/>和 <see cref="RuntimeArgumentHandle"/> 类型,或者这些类型的数组。 或 包含 t 的程序集是一个用 <see cref="AssemblyBuilderAccess.Save"/> 创建的动态程序集</exception> /// <exception cref="TargetInvocationException">正在被调用的构造函数引发了一个异常</exception> /// <exception cref="MethodAccessException">调用方没有权限调用此构造函数</exception> /// <exception cref="MemberAccessException">无法创建抽象类的实例,或者此成员是使用晚期绑定机制调用的</exception> /// <exception cref="InvalidComObjectException">未通过 Overload:<see cref="Type.GetTypeFromProgID"/> 或 Overload:<see cref="Type.GetTypeFromCLSID"/> 获取 COM 类型</exception> /// <exception cref="COMException">t 是一个 COM 对象,但用于获取类型的类标识符无效,或标识的类未注册</exception> /// <exception cref="TypeLoadException">t 不是有效类型</exception> /// <exception cref="TargetException">尝试调用一个不存在的属性</exception> /// <returns>指定的对象实例</returns> public object GetObject(string sectionKey, Type t) { if (t == null) { throw new ArgumentNullException("t"); } if (!this._object.ContainsKey(sectionKey)) // 如果不存在这个名称 { throw new ArgumentException("未能找到与传入节名匹配的节点, 请检查节名是否有效", "sectionKey"); } // 实例化对象 object instance = Activator.CreateInstance(t, true); // 获取属性列表 List <PropertyInfo> properties = new List <PropertyInfo> (t.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)); // 获取节点 ISection section = this._object[sectionKey]; foreach (KeyValuePair <string, IValue> item in section) { if (properties.Count == 0) { throw new TargetException(string.Format("正在尝试调用一个不存在的属性 {0} 引发异常", item.Key)); } for (int i = 0; i < properties.Count; i++) { IniKeyAttribute keyAttribute = properties[i].GetCustomAttribute <IniKeyAttribute> (); if ((keyAttribute != null && keyAttribute.KeyName.Equals(item.Key)) || properties[i].Name.Equals(item.Key)) { MethodInfo method = properties[i].GetSetMethod(true); if (method.GetParameters().Count() == 0) { method.Invoke(instance, new object[] { item.Value }); } properties.RemoveAt(i); break; } } } return(instance); }