3

早上好。

我需要将几乎任何类型的可序列化对象序列化为*.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属性值(对不起,属性名称,当我生气时,我的命名约定会发疯),没有别的。

我知道,这是一个相当“解决我的问题”的问题,但我找不到可以理解的来源,我可以完全反映一个对象及其属性名称和值的处理。
所以我向熟练的开发人员寻求帮助,向我指出一些来源,我快疯了。:-) 非常感谢,
南多

4

0 回答 0