将通用对象序列化为实现自定义IFormatter的* .INI文本文件

时间:2012-09-24 14:20:59

标签: c# serialization ini

早上好。

我需要序列化几乎所有可序列化的对象到* .INI文件
我正在尝试实现IFormatter,其中void Serialize(Stream, object)方法从对象实例获取属性信息,然后为基本类型或部分写入键/值+复杂类型的键/值。

将此代码作为序列化对象的示例。

[Serializable]
public class EmployeeList
{
    #region Properties
    public List<Employee> Employees { get; private set; }

    public string Banana { get; set; }
    #endregion


    #region Constructors
    public EmployeeList()
    {
        Employees = new List<Employee>();
    }
    #endregion


    #region Public Methods
    public void Serialize()
    {
        IFormatter formatter = new IniFormatter();

        using (FileStream outputStream = File.Create("employees.ini"))
        {
            try
            {
                formatter.Serialize(outputStream, this);
            }
            catch (SerializationException ex)
            {
                //...
            }
        }
    }
    #endregion
}

[Serializable]
public class Employee
{
    #region Properties
    public string Name
    {
        get;
        set;
    }

    public Gender Gender
    {
        get;
        set;
    }

    public List<Role> Roles
    {
        get;
        set;
    }
    #endregion


    #region Constructors
    public Employee()
    {
    }
    #endregion
}

[Serializable]
public enum Gender
{
    Male,
    Female,
    Other
}

[Serializable]
public class Role
{
    public string Name
    {
        get;
        set;
    }

    public int Value
    {
        get;
        set;
    }


    #region Constructors
    public Role()
    {

    }
    #endregion
}

好吧,因为我试图通过反射获取属性名称和值,所以一切都显得微不足道;我在尝试反映System.Reflection.TargetParameterCountException时不断获得List<Employee>(请参阅方法pi.GetValue(obj, null);,其中piPropertyInfo)。

这是我IniFormatter的代码:

public class IniFormatter : IFormatter
{
    #region Properties
    public ISurrogateSelector SurrogateSelector { get; set; }

    public SerializationBinder Binder { get; set; }

    public StreamingContext Context { get; set; }
    #endregion


    #region Constructors
    public IniFormatter()
    {
        Context = new StreamingContext(StreamingContextStates.All);
    }
    #endregion


    #region IFormatter Members
    public object Deserialize(Stream serializationStream)
    {
        throw new NotImplementedException();
    }

    public void Serialize(Stream serializationStream, object graph)
    {
        var propertyInfos = graph.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
        StreamWriter sw = new StreamWriter(serializationStream);

        foreach (var propertyInfo in propertyInfos)
        {
            if (!propertyInfo.CanRead)
            {
                continue;
            }

            if (Attribute.IsDefined(propertyInfo, typeof (NonSerializedAttribute)))
            {
                continue;
            }

            if (propertyInfo.PropertyType.IsPrimitive)
            {
                sw.WriteLine("{0}={1}", propertyInfo.Name, propertyInfo.GetValue(graph, null));
            }

            //object/complex types need to recursively call this method until the end of the tree is reached
            else
            {
                var complexType = GetPropertyValue(graph, propertyInfo.Name);
                Serialize(serializationStream, complexType);
            }
        }

        sw.Close();
    }
    #endregion


    public static object GetPropertyValue(object sourceObject, string propertyName)
    {
        if (sourceObject == null)
        {
            return null;
        }

        object obj = sourceObject;

        // Split property name to parts (propertyName could be hierarchical, like obj.subobj.subobj.property
        string[] propertyNameParts = propertyName.Split('.');

        foreach (string propertyNamePart in propertyNameParts)
        {
            if (obj == null)
            {
                return null;
            }

            // propertyNamePart could contain reference to specific 
            // element (by index) inside a collection
            if (!propertyNamePart.Contains("["))
            {
                PropertyInfo pi = obj.GetType().GetProperty(propertyNamePart, BindingFlags.Public | BindingFlags.Instance);
                if (pi == null)
                {
                    return null;
                }

                obj = pi.GetValue(obj, null);
            }
            else
            {
                // propertyNamePart is a reference to specific element 
                // (by index) inside a collection
                // like AggregatedCollection[123]
                // get collection name and element index
                int indexStart = propertyNamePart.IndexOf("[") + 1;
                string collectionPropertyName = propertyNamePart.Substring(0, indexStart - 1);
                int collectionElementIndex = Int32.Parse(propertyNamePart.Substring(indexStart, propertyNamePart.Length - indexStart - 1));
                //   get collection object
                PropertyInfo pi = obj.GetType().GetProperty(collectionPropertyName, BindingFlags.Public | BindingFlags.Instance);
                if (pi == null)
                {
                    return null;
                }

                object unknownCollection = pi.GetValue(obj, null);
                //   try to process the collection as array
                if (unknownCollection.GetType().IsArray)
                {
                    object[] collectionAsArray = unknownCollection as Array[];
                    obj = collectionAsArray[collectionElementIndex];
                }
                else
                {
                    //   try to process the collection as IList
                    IList collectionAsList = unknownCollection as IList;
                    if (collectionAsList != null)
                    {
                        obj = collectionAsList[collectionElementIndex];
                    }
                    else
                    {
                        // ??? Unsupported collection type
                    }
                }
            }
        }

        return obj;
    }
}

我从控制台应用程序运行测试,执行此操作:

            Employee employee = new Employee {Name = "Nando", Gender = Gender.Male, Roles = new List<Role> {new Role {Name = "CEO", Value = 1}}};

        EmployeeList employeeList = new EmployeeList();
        employeeList.Banana = "It's delicious!";
        employeeList.Employees.Add(employee);

        employeeList.Serialize();

我可以获得Banana属性值(对不起属性名称,当我生气时,我的命名约定变得疯狂),没有别的。

这是一个非常“解决我的问题”的问题,我知道,但我无法找到理解的来源我可以完全反映一个对象与其属性名称和值的交易。
所以我请熟练的开发人员帮忙指出一些消息来源,我疯了。 :-)非常感谢,
Nando

0 个答案:

没有答案
相关问题