2016-05-19 4 views
1

У меня проблема. Скажем, у меня есть общий класс, который может иметь общие свойства других классов и может даже иметь список других классов. Если у меня есть функция, какРекурсия на вложенных общих классах

public void Read<T>() where T: class, new() 
{ 

    // Create an instance of our generic class 
    var model = new T(); 
    var properties = typeof(T).GetProperties(); 

    // Loop through the objects properties 
    for(var property in properties) { 

     // Set our value 
     SetPropertyValue(property, model, "test"); 
    } 
} 

private void SetPropertyValue(PropertyInfo property, object model, string value) { 

    // Set our property value 
    property.SetValue(model, value, null); 
} 

, что будет работать, если у меня был класс вроде этого:

public class Person 
{ 
    public string Name { get; set; } 
} 

и я применит Read метод, как это:

Read<Person>(); 

Но если моя модель была такой:

public class Person 
{ 
    public string Name { get; set; } 
    public Company Company { get; set; } 
} 

public class Company 
{ 
    public string Name { get; set; } 
} 

И я попытался вызвать метод . Прочтите метод еще раз, он потерпит неудачу из-за свойства, у которого есть собственный список свойств. Что было бы лучше, если бы оно пересекло их тоже. Есть ли способ сделать это?

+0

Просто внесите универсальный вариант вашего метода чтения, в дополнение к универсальному. Из generic - вызов не общей версии, чтобы не повторять код слишком много. Затем, когда вы рекурсируете - просто вызовите не-общую версию с типом свойства. Не общие версии очень часто бывают хорошими. – Evk

ответ

1

Этот answer может помочь. Вы должны закончить с чем-то вроде этого:

if (t.IsPrimitive || t == typeof(Decimal) || t == typeof(String) || ...) 
    SetPropertyValue(property, model, "test"); 
else 
    // You will have to recode this line, 
    // it's just to show you the idea how you can work around 
    SetPropertyValue(property, model, Read.MakeGeneric(property.Type)()); 

Вам также необходимо вернуть переменную модели из метода Read.

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

1

Вы можете установить значение свойства непосредственно, если оно является строкой, в противном случае вы можете вернуть значение метода, аналогичного Read, которое принимает Type в качестве параметра для создания модели и рекурсивно заполняет ее свойства.

public void Read<T>() where T : class, new() 
{ 
    // Create an instance of our generic class 
    var model = new T(); 
    var properties = typeof(T).GetProperties(); 

    // Loop through the objects properties 
    foreach(var property in properties) 
    { 
     // Set our value 
     SetPropertyValue(property, model, "test"); 
    } 
} 

private void SetPropertyValue(PropertyInfo property, object model, string value) 
{ 
    if (property.PropertyType == typeof(string)) 
    { 
     // Set our property value 
     property.SetValue(model, value, null); 
    } 
    else 
    { 
     var submodel = Read(property.PropertyType); 
     property.SetValue(model, submodel, null); 
    } 
} 

private object Read(Type type) 
{ 
    if (!IsTypeSupported(type)) 
    { 
     throw new ArgumentException(); 
    } 

    var model = type.GetConstructor(new Type[0]).Invoke(new object[0]); 
    var properties = type.GetProperties(); 

    foreach (var property in properties) 
    { 
     SetPropertyValue(property, model, "test"); 
    } 

    return model; 
} 

private bool IsTypeSupported(Type type) 
{ 
    return type.IsClass && type.GetConstructor(new Type[0]) != null; 
} 
+1

Конечно, это предполагает, что OP никогда не придется иметь дело с другими примитивными типами, такими как 'int' или' double'. –

Смежные вопросы