c # Рекурсивные отражения и общие списки, устанавливающие свойства по умолчанию - PullRequest
3 голосов
/ 15 апреля 2010

Я пытаюсь использовать рефлексию для достижения следующего:

Мне нужен метод, в котором я передаю объект, и этот метод будет рекурсивно создавать экземпляр объекта с дочерними объектами и устанавливать свойства со значениями по умолчанию. Мне нужно, чтобы весь объект был создан, пройдя столько уровней, сколько нужно.

этот метод должен иметь возможность обрабатывать объект с несколькими свойствами, которые будут общими списками других объектов.

Вот мой пример кода (я получаю исключение несоответствия количества параметров, когда получаю объект, содержащий List<AnotherSetObjects>:

private void SetPropertyValues(object obj)
{
    PropertyInfo[] properties = obj.GetType().GetProperties();

    foreach (PropertyInfo property in properties)
    {
        if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && property.PropertyType.FullName.Contains("BusinessObjects"))
        {
            Type propType = property.PropertyType;

            var subObject = Activator.CreateInstance(propType);
            SetPropertyValues(subObject);
            property.SetValue(obj, subObject, null);
        }
        else if (property.PropertyType == typeof(string))
        {
            property.SetValue(obj, property.Name, null);
        }
        else if (property.PropertyType == typeof(DateTime))
        {
            property.SetValue(obj, DateTime.Today, null);
        }
        else if (property.PropertyType == typeof(int))
        {
            property.SetValue(obj, 0, null);
        }
        else if (property.PropertyType == typeof(decimal))
        {
            property.SetValue(obj, 0, null);
        }
    }
}

Спасибо

Ответы [ 2 ]

1 голос
/ 15 апреля 2010

Вы можете отфильтровать, проверив property.PropertyType.IsGeneric, что верно для универсальных контейнеров. Если вам нужно, также проверьте на property.PropertyType.IsArray.

Кроме того, вы также можете избежать использования нестандартных контейнеров. В этом случае проверьте, чтобы объект имел типы интерфейсов таких контейнеров. Например - IList.

bool isList(object data)
{
    System.Collections.IList list = data as System.Collections.IList;
    return list != null;
}

...
if (isList(obj)) {
    //do stuff that take special care of object which is a List
    //It will be true for generic type lists too!
}
0 голосов
/ 15 апреля 2010

Это хитрый:)

Когда вы передаете инициализатору объект, содержащий общий список некоторого типа "BusinessObjects" в качестве свойства, тогда это свойство передаст ваш

if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && property.PropertyType.FullName.Contains("BusinessObjects"))

выражение, потому что экземплярный типовой экземпляр будет иметь такое имя:

System.Collections.Generic.List`1[[ConsoleApplication92.XXXBusinessObjects, ConsoleApplication92, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]

В результате вызывается метод инициализатора с самим списком в качестве параметра. В списке будет индексатор с именем Item типа SomeBusinessObjects. Это также пройдет вышеупомянутое условие, поэтому вы также попытаетесь инициализировать его. В результате получается что-то вроде этого:

obj.ListProperty.Item = new SomeBusinessObject();

тогда как индексатор может использоваться только при такой инициализации

obj.ListProperty[0] = new SomeBusinessObject();

Это показывает, что на самом деле вам не хватает параметра.

Что вы собираетесь с этим делать, зависит от вас:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...