lundi 1 août 2016

Converting xml to hierarchical data in c# with classes

I have a class that goes and gets data from a database and it gets the as xml data in the form of hierarchical data.

below is a sample of the data:

<SecurityGroups>
<SecurityGroup>
    <Id>1</Id>
    <Name>View</Name>
</SecurityGroup>
<SecurityGroup>
    <Id>2</Id>
    <Name>Fill</Name>
    <SecurityUsers>
        <SecurityUser>
            <securityId>2</securityId>
            <userId>2</userId>
            <username>Fill</username>
        </SecurityUser>
        <SecurityUser>
            <securityId>2</securityId>
            <userId>3</userId>
            <username>FillOne</username>
        </SecurityUser>
        <SecurityUser>
            <securityId>2</securityId>
            <userId>4</userId>
        <username/></SecurityUser>
    </SecurityUsers>
</SecurityGroup>
<SecurityGroup>
    <Id>3</Id>
    <Name>Update</Name>
    <SecurityUsers>
        <SecurityUser>
            <securityId>3</securityId>
            <userId>5</userId>
            <username>Update</username>
        </SecurityUser>
        <SecurityUser>
            <securityId>3</securityId>
            <userId>6</userId>
            <username>UpdateOne</username>
        </SecurityUser>
    </SecurityUsers>
</SecurityGroup>
<SecurityGroup>
    <Id>4</Id>
    <Name>Admin</Name>
    <SecurityUsers>
        <SecurityUser>
            <securityId>4</securityId>
            <userId>1</userId>
            <username>JTays</username>
        </SecurityUser>
    </SecurityUsers>
</SecurityGroup>

Which works great! Now, I have a class that uses reflection to convert from xml to models that i am eventually going to use in a treeview. below is the entire class.

the models are:

[XmlRootAttribute(Namespace = "", IsNullable = false)]
public class SecurityGroup
{
    [XmlElementAttribute(Form = XmlSchemaForm.Unqualified)]
    public int Id { get; set; }
    [XmlElementAttribute(Form = XmlSchemaForm.Unqualified)]
    public string Name { get; set; }
    [XmlElementAttribute("SecurityUser",
        Form = XmlSchemaForm.Unqualified)]
    public List<SecurityUser> SecurityUsers { get; set; }
}

public class SecurityUser:IEntity
{
    [XmlElement(Form = XmlSchemaForm.Unqualified)]
    public int SecurityId { get; set; }
    [XmlElementAttribute(Form = XmlSchemaForm.Unqualified)]
    public int UserId { get; set; }
    [XmlElementAttribute(Form = XmlSchemaForm.Unqualified)]
    public string Username { get; set; }

    public int Id { get; set; }
}

Here is the class that converts.

    public class AdminManager : IAdminService
{
    public IEnumerable<SecurityGroup> SecurityGroups()
    {
        IEnumerable<SecurityGroup> list = null;
        XmlDocument xmlDoc = new XmlDocument();
        using (var c = new FMContext())
        {
            var xmlData = c.Database.SqlQuery<string>("AllSecurtyUsersProc").FirstOrDefault();
            if (xmlData != null)
            {
                xmlDoc.LoadXml(xmlData);
                list = ConvertXmlToClass<SecurityGroup>(xmlDoc, "/SecurityGroups/SecurityGroup");
            }
        }
        return list;
    }

    public static IEnumerable<T> ConvertXmlToClass<T>( XmlDocument doc, string nodeString)
        where T:class, new()
    {
        var xmlNodes = doc.SelectNodes(nodeString);
        List<T> list = new List<T>();
        foreach (XmlNode node in xmlNodes)
        {
            var item = GetNewItem<T>(node);
            list.Add(item);
        }
        return list;
    }

    public static T GetNewItem<T>(XmlNode node)
        where T:class, new()
    {
        var type = typeof (T);
        var item = new T();
        var properties = type.GetProperties();
        foreach (var property in properties)
        {
            var propertyType = property.PropertyType;
            var propertyName = property.Name;
            object value = null;
            if (IsEnumerable(property))
            {
                value = GetNodeCollectionValue(property,node);
            }
            else
            {
                value = GetNodeValue(node, propertyName);
            }
            if (value!=null)
            {
                property.SetValue(item, Convert.ChangeType(value, propertyType), null);
            }

        }
        return item;
    }

    private static object GetNodeCollectionValue(PropertyInfo property, XmlNode node)
    {
        var doc = new XmlDocument();
        var itemType = property.PropertyType.GenericTypeArguments[0];
        var xml = $"<{property.Name}><{itemType.Name}>{node.InnerXml}</{itemType.Name}></{property.Name}>";
        doc.LoadXml(xml);
        if (itemType != null)
        {
            var type = typeof (AdminManager);
            var methodInfo = type.GetMethod("ConvertXmlToClass");
            if (methodInfo!=null)
            {
                var method = methodInfo.MakeGenericMethod(itemType);
                if (method != null)
                {
                    object[] args = {doc, property.Name};
                    object result = method.Invoke(null, args);
                    return result;
                }
            }

        }

        return new object();
    }


    private static bool IsEnumerable(PropertyInfo property)
    {
        var type = property.PropertyType;
        return typeof (IEnumerable).IsAssignableFrom(type) && type.IsGenericType;
    }

    private static object GetNodeValue(XmlNode node, string nodeName)
    {
        var i = node[nodeName]?.InnerText;
        return i ?? null;
    }
}

Okay, so now my issue. My problem is that when it converts it doesn't get the correct data for the SecurtyUsers classes it adds them as an object, but everything is null or 0. Can someone help me figure out where i went worng?





Aucun commentaire:

Enregistrer un commentaire