2015-01-22 5 views
0

Итак, моя проблема в том, что я хочу удалить нули для всех своих строк в сложных объектах, таких как POCOs и DTO. Я могу это сделать, но метод, который я делаю, кажется, что это может быть лучше. Поэтому я подумал, что кто-то из Stack Overflow имеет лучший способ.Хотите вызвать базовый класс, используя общий с этим «дочерним» классом

Базовый класс:

public class PropertyEmptySetter<T> where T : class 
{ 
    T obj { get; set; } 

    public PropertyEmptySetter(T myObj) 
    { 
     obj = myObj; 
     UpdateStringProperties(); 
    } 

    public PropertyEmptySetter() 
    { 
    } 

    public void UpdateStringProperties() 
    { 
     foreach (var prop in obj.GetType().GetProperties().ToList()) 
     { 
      if (prop.PropertyType == (typeof(string))) 
      { 
       if(prop.GetValue(obj) == null) 
        prop.SetValue(obj, String.Empty); 
      } 
     } 
    } 
} 

Детский класс (ПОКО Object):

public class POCO : PropertyEmptySetter<POCO> 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string Purpose { get; set; } 

    public POCO() 
    { 
     var setter = new PropertyEmptySetter<POCO>(this); 
    } 
} 

Тестирование это работает:

private static string _s = ""; 

static void Main(string[] args) 
{ 

    var item = new POCO {Id = 1, Name = "Brett", Description = "Me"}; 

    var props = item.GetType().GetProperties(); 
    foreach (var prop in props) 
    { 
     _s += "Type: " + prop.Name + "\tValue:" + (prop.GetValue(item) ?? "NULL") + Environment.NewLine; 

    } 

    Console.WriteLine(_s); 
    Console.ReadLine(); 
} 

Так что вышеуказанные работы, но я надеялся, чтобы сократить его что-то вроде детского конструктора, заявив:

public POCO() : base(this) 

Ehh, ehhh. Visual Studio не нравится это и заявляет, что «не может использовать„это“в инициализаторе члена»

Или иметь конструктор без параметров в базе сделать что-то вроде

public PropertyEmptySetter() 
{ 
    obj = (child) // Yes I know this does not exist 
     UpdateStringProperties(); 
} 

Я в основном надеялся эшафот всей логики так что наследование просто знает: «О, вы хотите, чтобы этот объект, который вы создаете, ПРЯМО СЕЙЧАС, получил!» Кажется, что я должен сделать это в рамках конструктора и не могу обойти это. Но я могу просто не знать о более легком пути. Я не хочу этого, когда экземпляр объекта за его пределами, я хочу это, чтобы он просто поднимался, когда объект создается внутри себя и базового класса. Возможно ли это или это метод, который я показываю самым простым способом?

ответ

2

Проще всего сделать так, чтобы сделать PropertyEmptySetter не общим, как это не должно быть. Он просто работает на this и каждый класс в наследуется от него проходит this просто будучи PropertyEmptySetter:

public class PropertyEmptySetter 
{ 
    public PropertyEmptySetter() 
    { 
     UpdateStringProperties(); 
    } 

    public void UpdateStringProperties() 
    { 
     foreach (var prop in obj.GetType().GetProperties().ToList()) 
     { 
      if (prop.PropertyType == (typeof(string))) 
      { 
       if (prop.GetValue(obj) == null) 
        prop.SetValue(obj, String.Empty); 
      } 
     } 
    } 
} 

class POCO : PropertyEmptySetter 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string Purpose { get; set; } 
} 

Однако, если вы все еще хотите, чтобы сделать его родовым вы можете использовать статический метод строителя:

class Poco 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string Purpose { get; set; } 

    private Poco() {} 

    public static Poco CreatePoco() 
    { 
     var poco = new Poco(); 
     new PropertyEmptySetter<POCO>(poco); 
     return poco; 
    } 
} 
-1

Я думаю, что вам не хватает ключевых навыков в C# и . NET.

Что касается вашего тестового приложения, то, во-первых, всегда сложно связать строки в цикле. Строки неизменяемы в . NET. Каждый раз, когда вы объединяете строки, вы создаете новую строку. Используйте StringBuilder вместо

var sb = new StringBuilder(); 
foreach (var prop in item.GetType().GetProperties()) 
{ 
    sb.Append("Type: "); 
    sb.Append(prop.Name); 
    sb.Append("\tValue:"); 
    var value = prop.GetValue(item); 
    if (value == null) 
    { 
     sb.Append(" NULL"); 
    } 
    else 
    { 
     sb.Append(" ["); 
     sb.Append(value); 
     sb.Append("]"); 
    } 
    sb.Append(Environment.NewLine); 
} 

Console.WriteLine(sb.ToString()); 

Во-вторых, ваша реализация не работает, и вы не испытывали на то, что вы пытаетесь избежать.Если вы пытаетесь с этим:

var item = new POCO {Id = 1, Name = "Brett", Description = null}; 

вы получите это:

Type: Id Value: [1] 
Type: Name Value: [Brett] 
Type: Description Value: NULL 
Type: Purpose Value: [] 

Вы получение от базовой Классе только criate переменного в конструкторе, что вы бросаете прочь, не делая ничего полезным, потому что все строки в классе POCO все еще инициализированы, поэтому нулевые.

Если вы удалите что из POCO конструктора:

public POCO() 
{ 
} 

и obj от PropertyEmptySetter<T>:

public class PropertyEmptySetter<T> where T : class 
{ 
    public PropertyEmptySetter() 
    { 
    } 

    public void UpdateStringProperties() 
    { 
     foreach (var prop in this.GetType().GetProperties()) 
     { 
      if (prop.PropertyType == (typeof(string))) 
      { 
       if(prop.GetValue(this) == null) 
        prop.SetValue(this, String.Empty); 
      } 
     } 
    } 
} 

и использовать его как это:

var item = new POCO {Id = 1, Name = "Brett", Description = null}; 
item.UpdateStringProperties(); 

Я думаю, что вы» Получите то, что вы ищете:

Type: Id Value: [1] 
Type: Name Value: [Brett] 
Type: Description Value: [] 
Type: Purpose Value: [] 

В ООП (объектно-ориентированное программирование) концепция hinheritance и parent-child вводит в заблуждение. Это не похоже на POCO является ребенком PropertyEmptySetter<T> и PropertyEmptySetter<T> является родителем POCO. POCO также является PropertyEmptySetter<T> (более конкретно, PropertyEmptySetter<POCO>), но PropertyEmptySetter<T> необязательно является POCO.

Если вы не хотите, чтобы связать свои Pocos к PropertyEmptySetter<T> вы можете добавить статический метод PropertyEmptySetter<T>:

public class PropertyEmptySetter<T> where T : class 
{ 
    public void UpdateStringProperties() 
    { 
     UpdateStringProperties(this as T); 
    } 

    public static T UpdateStringProperties(T obj) 
    { 
     if (obj == null) 
     { 
      return null; 
     } 

     foreach (var prop in obj.GetType().GetProperties()) 
     { 
      if (prop.PropertyType == (typeof(string))) 
      { 
       if(prop.GetValue(obj) == null) 
        prop.SetValue(obj, String.Empty); 
      } 
     } 

     return obj; 
    } 
} 

и просто:

public class POCO : PropertyEmptySetter<POCO> 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public string Purpose { get; set; } 
} 

и использовать его как это:

var item = new POCO {Id = 1, Name = "Brett", Description = null}; 
PropertyEmptySetter<POCO>.UpdateStringProperties(item); 

И поэтапный статический метод возвращает POCO, вы можете ch айн это:

var anotherItem = PropertyEmptySetter<POCO>.UpdateStringProperties(item); 

И, кстати, вы ничего не делаете с ним, что не может быть сделано на struct, так что вы должны удалить class ограничение и просто сделать его класс расширения:

public static class PropertyEmptySetter 
{ 
    public static T UpdateStringProperties<T>(this T obj) where T : class 
    { 
     foreach (var prop in obj.GetType().GetProperties()) 
     { 
      if (prop.PropertyType == (typeof(string))) 
      { 
       if(prop.GetValue(obj) == null) 
        prop.SetValue(obj, String.Empty); 
      } 
     } 

     return obj; 
    } 
} 

и использовать UpdateStringProperties как метод экземпляра:

var item = new POCO {Id = 1, Name = "Brett", Description = null}; 
item = item.UpdateStringProperties(); 

компилятор даже определить тип в вызове UpdateStringProperties ,

+0

Ваш ответ нужно удалить: 1. «строка» неизменна, но не в том смысле, что ее нельзя изменить, вы идете по касательной к изменчивости, которая не имеет никакого отношения к вопросу. 2. Когда я добавляю в коллекцию из GetProperties объекта, я возвращаю коллекцию PropertyInfo на основе объекта, который он вызывает. Если я добавлю точку останова и посмотрю каждую информацию о свойствах, это легко увидеть. Вы заявляете что-то совершенно ложное от предположения. 3. Ваш конечный ответ имеет некоторые достоинства, но игнорирует основной запрос сделать это в строительстве НЕ внешним классом. – djangojazz

+0

Не хотите ли вы, чтобы нас всех расставили, чтобы определить и продемонстрировать то, что «полностью ложно»? –

+0

«Во-вторых, ваша реализация не работает, и вы не проверяли на то, чего пытаетесь избежать. Если вы попытаетесь с этим:« Вы принимаете то, что я не делал. Но вы правы, я мог бы сформулировать это как «Я хочу удалить null экземпляры» verus «Я хочу удалить nulls». В основном, весь ваш ответ был предположен, оскорбительный и оскорбительный, основанный на сделанных вами условиях, которые не были в этом примере. Вы могли бы сказать: «Явное назначение не учитывает этого». и со мной все будет в порядке. Вместо того, чтобы ты сделал то, что я сказал, чтобы не делать, а затем предположил, что это то, что я хотел. – djangojazz

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