Распознавание шаблонов в C # - PullRequest
0 голосов
/ 18 мая 2018

У меня есть два класса

public class ClassA
{
 public int ID { get; set; }
 public string Countries {get;set;}
 public string City { get;set; }
}

и

public class ClassB
{
 public int ID { get; set; }
 public string Countries {get;set;}
 public string Village{ get;set; }
}

Эти два класса находятся в другом классе

public class ComponentClass
{
   public List<ClassA> classAObj { get; set; }
   public List<ClassB> classBObj { get; set; }
}

Данные для ComponentClass поступает от третьей стороны, где данные для ClassA и ClassB схожи по структуре. «Город» в ClassA будет иметь данные в значениях, разделенных запятыми «Манчестер, Сидней» и т. Д., Аналогично деревням и значениям, разделенным запятыми.

Сейчас я строюнастраиваемый объект на бизнес-уровне, где я перебираю каждое свойство ComponentClass и извлекаю информацию.

Main()
{
  ComponentClass[] c = //Data from 3rd party;
  foreach(var data in c)
  {
    Parent p = new Parent();


    if(data.classAObj.count > 0)
    {
      Star s = new Star();
      s.Area = "infinite";
      s.Color = "red";
      List<string> sep = data.City.Split(',').Select(string.Parse).ToList();    
      foreach(var b in sep)
      {
       TinyStar t = new TinyStar();
       t.smallD = b;
       s.Values.Add(t);
       }
      p.Curves.Add(s);
     }


    if(data.classBObj.count > 0)
    {
      Star s2 = new Star();
      s2.Area = "infinite";
      s2.Color = "red";
      List<string> sep = data.Village.Split(',').Select(string.Parse).ToList();    
      foreach(var b in sep)
      {
       TinyStar t = new TinyStar();
       t.smallD = b;
       s2.Values.Add(t);
       }
      p.Curves.Add(s);
     }

   }
}

В приведенном выше коде два оператора if выполняют одну и ту же операцию, кроме имен свойств "City"и "Деревня".Я хочу упростить это, используя любой шаблон проектирования, возможно, шаблон стратегии, который я знаю только теоретически, или любые другие шаблоны.

Вот что я пробовал:

public abstract class Base
{
  public int ID { get; set; }
  public string Countries {get;set;}
}

public class ClassA : Base
{

 public string City { get;set; }
}


public class ClassB : Base
{
 public string Village{ get;set; }
}    

Я хочусделать это как обычный метод фабрики, который будет делать циклы и построить объект для меня, чтобы избежать дублирования кода

public void CommonMethod(Base)
{
  // How do I differentiate the properties for looping 
}

Ответы [ 4 ]

0 голосов
/ 18 мая 2018

Я использовал отражение, проверьте, работает ли оно у вас

public static void CommonMethod(dynamic collection)
{

        Parent p = new Parent();
        Star s = new Star();
        s.Area = "infinite";
        s.Color = "red";
        foreach (var data in collection)
        {
            var properties = data.GetType().GetProperties();

            foreach (var p in properties)
            {
                string propertytName = p.Name;

                var propertyValue = p.GetValue(data, null);

                if (propertytName == "City" || propertytName == "Village")
                {
                    List<string> sep = propertyValue.Split(',').ToList();
                    foreach (var b in sep)
                    {
                        TinyStar t = new TinyStar();
                        t.smallD = b;
                        s.Values.Add(t);
                    }
                    p.Curves.Add(s);
                }
            } 
        }
    }

    static void Main(string[] args)
    {
        ComponentClass[] c Data from 3rd party;
        foreach (var data in c)
        {
            CommonMethod(data.classAObj);
            CommonMethod(data.classBObj);
        }
}
0 голосов
/ 18 мая 2018

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

    public class ClassA
    {
     public int ID { get; set; }
     public string Countries {get;set;}
     public string Areas{ get;set; }
    }


public class ComponentClass
{
   public List<ClassA> classAObj { get; set; }
   public List<ClassA> classBObj { get; set; }
}


Main()
{
  ComponentClass[] c = //Data from 3rd party;
  foreach(var data in c)
  {
    Parent p = new Parent(); 
    GetParent   (p ,data.classAObj )
    GetParent   (p ,data.classBObj )
   }
}

void GetParent (Parent p, ClassA classObj){
 if(data.classAObj.count > 0)
    {
      Star s = new Star();
      s.Area = "infinite";
      s.Color = "red";
      List<string> sep = data.Areas.Split(',').Select(string.Parse).ToList();    
      foreach(var b in sep)
      {
       TinyStar t = new TinyStar();
       t.smallD = b;
       s.Values.Add(t);
       }
      p.Curves.Add(s);
     }
return p ;
}
0 голосов
/ 18 мая 2018

Я бы посоветовал унаследовать ClassA и ClassB от общей базы, как вы это сделали, а затем разыграть их после проверки типов.Если ваша единственная цель - свести к минимуму повторение кода, это поможет вам:

class Program
{
    static void Main(string[] args)
    {
        ComponentClass[] c = new List<ComponentClass>().ToArray();//Data from 3rd party;

        foreach (var data in c)
        {
            Parent p = new Parent();


            if (data.classObjs.Count > 0)
            {
                Star s = new Star
                {
                    Area = "infinite",
                    Color = "red"
                };
                foreach (var b in data.classObjs)
                {
                    string bStr = b.GetType() == typeof(ClassA) ? ((ClassA)b).City : ((ClassB)b).Village;

                    bStr = bStr.Split(',').Select(string.Parse).ToList();

                    TinyStar t = new TinyStar
                    {
                        smallD = bStr
                    };
                    s.Values.Add(t);
                }
                p.Curves.Add(s);
            }
        }
    }
    public class ComponentClass
    {
        public List<ClassObj> classObjs { get; set; }
    }

    public class ClassObj
    {
        public int ID { get; set; }
        public string Countries { get; set; }
    }

    public class ClassA : ClassObj
    {
        public string City { get; set; }
    }

    public class ClassB : ClassObj
    {
        public string Village { get; set; }
    }
}

Возможно, потребуется изменить рефакторинг на if...else или switch в зависимости от того, добавите ли вы больше классов типа ClassObj.

Имейте в виду, что GetType фактически запрашивает сборку (во время выполнения) и должен использоваться с осторожностью с точки зрения производительности, поскольку это может сильно замедлять работу приложений при частом выполнении.

0 голосов
/ 18 мая 2018

Если цель состоит в том, чтобы уменьшить повторение кода, эти два оператора могут быть преобразованы в одно действие следующим образом.

foreach(var data in c)
{
    Parent p = new Parent();

    Action<string> iAction = iString =>
    {
        Star s = new Star();
        s.Area = "infinite";
        s.Color = "red";
        List<string> sep = iString.Split(',').Select(string.Parse).ToList();

        foreach(var b in sep)
        {
            TinyStar t = new TinyStar();
            t.smallD = b;
            s.Values.Add(t);
        }
        p.Curves.Add(s);
    }

    if(data.classAObj.count > 0)
    {
        iAction(data.City);
    }

    if(data.classBObj.count > 0)
    {
        iAction(data.Village);
    }
}
...