Search code examples
c#classreflectioncomposite

Set value of composite classes using Reflection


I'm trying to create instance of an object that also have classes composed in to it:

[DataContract(Name = "share", Namespace = "")]
public class RequestShareDocument
{
    [DataMember(Order = 0)]
    public string profile_name { get; set; }
    [DataMember(Order = 1)]
    public List<RequestSigner> signers {get; set;}
    [DataMember(Order = 2)]
    public bool createcopy { get; set; }
}

[DataContract(Name = "signer", Namespace = "")]
public class RequestSigner
{
    [DataMember(Order = 0)]
    public string email { get; set; }
    [DataMember(Order = 1)]
    public string order { get; set; }
    [DataMember(Order = 2)]
    public string reminder { get; set; }
    [DataMember(Order = 3)]
    public RequestSignerPermissions permissions { get; set; }
    [DataMember(Order = 4)]
    public string signature_field { get; set; }
}

[DataContract(Name = "permissions", Namespace = "")]
public class RequestSignerPermissions
{
    [DataMember(Order = 0)]
    public bool save_locally {get;set;}
    [DataMember(Order = 1)]
    public string open_password { get; set; }
    [DataMember(Order = 2)]
    public DateTime accessible_after { get; set; }
    [DataMember(Order = 3)]
    public DateTime accessible_before { get; set; }
    [DataMember(Order = 4)]
    public string certify_level { get; set; }
}

I need to create an instance of class and serialize in to XML, but I don't know how to do this?

I'm able to create an instance of a class but when it comes to the List<T> property I'm not able to create it. I've already tried this:

if (typeof(IEnumerable).IsAssignableFrom(item.PropertyType))
    IList list = (IList)Activator.CreateInstance(typeof(List<>));

...and to serialize I'm using:

XmlSerializer mySerializer = new XmlSerializer(typeof(T), new
    XmlRootAttribute(RootElementName));       
StringWriter sww = new StringWriter();
XmlWriter writer = XmlWriter.Create(sww, new XmlWriterSettings()
    { OmitXmlDeclaration = true, Indent = true });
mySerializer.Serialize(writer, item);
writer.Close();
sww.Close();

Problem is when I loop all properties and reach the List I don't know how to create an instance of List. Is it possible or am I doing something wrong?


Solution

  • If I have understood correctly, this code does what you want:

    public static object InitializeTarget(Type type)
        {
            object target = CreateObject(type);
            foreach (PropertyInfo propertyInfo in type.GetProperties())
            {
                if (propertyInfo.PropertyType.IsClass && propertyInfo.CanWrite
                    && propertyInfo.PropertyType != typeof(string)
                    && (propertyInfo.IsDefined(typeof(DataMemberAttribute), true)))
                    propertyInfo.SetValue(target, InitializeTarget(propertyInfo.PropertyType), null);
            }
            return target;
        }
    
        public static object CreateObject(Type type)
        {
            if (typeof(IList).IsAssignableFrom(type) && type.IsGenericType)
            {
                Type[] genericArguments = type.GetGenericArguments();
                if (genericArguments.Length == 1)
                {
                    var list = (IList)Activator.CreateInstance(type);
                    //Adding default value
                    list.Add(CreateObject(genericArguments[0]));
                    return list;
                }
            }
            //If the object is only to serialize, you can use it
            return FormatterServices.GetUninitializedObject(type);
            //or
            //            return Activator.CreateInstance(type);
        }