2015-01-27 3 views
0

Я работаю над приложением веб-сервиса с несколькими (11) вызовами веб-сервиса.Обычно заполняют разные классы.

Для каждого веб-сервиса, мне нужно заполнить мыло Body из массива строк, как это:

if (aMessage[(int)DCSSCustomerUpdate_V3.Branch].ToString().Length != 0) 
{ 
    wsSoapBody.Branch = aMessage[(int)DCSSCustomerUpdate_V3.Branch].ToString(); 
} 

aMessage[int] является массив строк, и [INT] определяется перечисляемого константой - в этом случае она определяется следующим образом:

private enum DCSSCustomerUpdate_V3 
{ 
    MsgType = 0, 
    MsgVersion = 1, 
    WSName = 2, 
    ReplyTo = 3, 
    SourceSystem = 4, 
    ... 
} 

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

частичный класс определен в WSDL, как это:

public partial class DCSSCustomerUpdateType 
{ 
    private string instIdField; 
    private string branchField; 
    ... 
} 

Вместо того, чтобы делать это для каждого из них в отдельности (в каждом из 11 пользовательских службы классов), интересно, есть ли способ передать в частичном классе wsSoapBody (вместе со строковым массивом) и пропустить все члены класса, назначая значения из массива строк?

EDIT:

Я искал и нашел SO: 531384/how-to-loop-through-all-the-properties-of-a-class?

Так что я попытался это:

public static void DisplayAll(Object obj, string[] aMessage) 
    { 
     Type type = obj.GetType(); 
     PropertyInfo[] properties = type.GetProperties(); 

     foreach (PropertyInfo property in properties) 
     { 
      string value = aMessage[property.Name].ToString(); 
      System.Diagnostics.Debug.WriteLine("Name: " + property.Name + ", Value: " + property.GetValue(obj, null)); 
     } 
    } 

но string value = aMessage[property.Name].ToString(); не будет компилироваться - как он ищет ИНТ вернулся из перечислимая постоянная ...

так куда я могу перейти оттуда?

ответ

1

Попробуйте так

DCSSCustomerUpdate_V3 t = (DCSSCustomerUpdate_V3)Enum.Parse(typeof(DCSSCustomerUpdate_V3), property.Name); 
string value = aMessage[(int)t].ToString(); 

вы также можете использовать метод Enum.TryParse

Для общий тип Enum более или менее

public static void DisplayAll<TEnum>(Object obj, string[] aMessage) where TEnum : struct, IComparable, IFormattable, IConvertible 
     { 
      if (!typeof(TEnum).IsEnum) 
      { 
       throw new ArgumentException("T must be an enumerated type"); 
      } 

      Type type = obj.GetType(); 
      PropertyInfo[] properties = type.GetProperties(); 

      foreach (PropertyInfo property in properties) 
      { 
       TEnum t = (TEnum)Enum.Parse(typeof(TEnum), property.Name); 
       string value = aMessage[t.ToInt32(Thread.CurrentThread.CurrentCulture)].ToString(); 
       System.Diagnostics.Debug.WriteLine("Name: " + property.Name + ", Value: " + property.GetValue(obj, null)); 
      } 
     } 

просмотреть этот Create Generic method constraining T to an Enum

+0

, но что, если ' DCSSCustomerUpdate_V3' является общим, переданным, как бы передать его? –

+0

Я обновил сообщение – Fabio

+0

, так как я могу установить значения моего класса - это 'property.SetValue', прежде чем я верну класс к моему методу вызова? –

1

Я не знаю, если я понял ваш вопрос:

if (aMessage[(int)DCSSCustomerUpdate_V3.Branch].ToString().Length != 0) 
{ 
    wsSoapBody.Branch = aMessage[(int)DCSSCustomerUpdate_V3.Branch].ToString(); 
} 

Так у вас есть это перечисление DCSSCustomerUpdate_V3, которые члены соответствуют именам имущественных wsSoapBody класса, и вы не хотите, чтобы повторить подобный код один выше, но использовать петлю, правильно?

Вы можете просто цикл по всем элементам DCSSCustomerUpdate_V3 и установите значение свойства, как:

// type of the enum; pass in as parameter 
var enumType = typeof(DCSSCustomerUpdate_V3) 

// get the type of wsSoapBody 
var t = wsSoapBody.GetType(); 

// loop over all elements of DCSSCustomerUpdate_V3 
foreach(var value in Enum.GetValues(enumType)) 
{ 
    if (aMessage[(int)value].ToString().Length != 0) 
    { 
     // set the value using SetValue 
     t.GetProperty(value.ToString()).SetValue(wsSoapBody, aMessage[(int)value].ToString()); 
    } 
} 
+0

Да если я хочу использовать общий метод в моем классе common.cs, как бы определить и передать в перечислимой константе? У меня есть одно перечисление для каждой из различных веб-сервисов ... так что 'DCSSCustomerUpdate_V3' на самом деле будет общим перечислением, переданным в ... –

+0

Вы можете просто передать тип перечисления (назовем его' type_of_the_enum') в вопросе и вместо 'foreach (значение DCSSCustomerUpdate_V3 в Enum.GetValues ​​(typeof (DCSSCustomerUpdate_V3)))' просто использовать 'foreach (значение var в Enum.GetValues ​​(type_of_the_enum))' – sloth

+0

Я обновил свой ответ – sloth

0

так благодаря Fabio и Sloth, вот окончательный код, который мы построили:

public static void DisplayAll<TEnum>(Object obj, string[] aMessage) where TEnum : struct, IComparable, IFormattable, IConvertible 
/* 
* see https://stackoverflow.com/questions/28168982/generically-populate-different-classes-members 
* 
*/ 
{ 
try 
{ 
    // get the type of wsSoapBody 
    Type type = obj.GetType(); 

    PropertyInfo[] properties = type.GetProperties(); 

    foreach (PropertyInfo property in properties) 
    { 
    try 
    { 
     if (Enum.IsDefined(typeof(TEnum), property.Name)) 
     { 

     TEnum t = (TEnum)Enum.Parse(typeof(TEnum), property.Name, true); 

     System.Diagnostics.Debug.WriteLine("Name: " + property.Name + ", Value: " + property.GetValue(obj, null) + "Type: " + property.PropertyType); 

     // property.GetValue(obj, null).ToString() != "" && 
     if (t.ToInt32(Thread.CurrentThread.CurrentCulture) < aMessage.GetUpperBound(0) && aMessage[t.ToInt32(Thread.CurrentThread.CurrentCulture)].ToString() != "") 
     { 
      switch (property.PropertyType.ToString()) 
      { 
      case "System.String": 
       string value = aMessage[t.ToInt32(Thread.CurrentThread.CurrentCulture)].ToString(); 
       property.SetValue(obj, value, null); 
       break; 
      case "System.Int32": 
       int iValue = Convert.ToInt32(aMessage[t.ToInt32(Thread.CurrentThread.CurrentCulture)].ToString()); 
       property.SetValue(obj, iValue, null); 
       break; 
      case "System.Int64": 
       long lValue = Convert.ToInt64(aMessage[t.ToInt32(Thread.CurrentThread.CurrentCulture)].ToString()); 
       property.SetValue(obj, lValue, null); 
       break; 
      case "System.DateTime": 
       DateTime dtValue = DateTime.ParseExact(aMessage[t.ToInt32(Thread.CurrentThread.CurrentCulture)].ToString(), "ddMMyyyy", System.Globalization.CultureInfo.InvariantCulture); 
       property.SetValue(obj, dtValue, null); 
       break; 
      default: 
       System.Diagnostics.Debugger.Break(); 
       break; 
      } 
     } 
     else 
     { 
      logBuilder("Common.DisplayAll", "Info", "", property.Name + " is empty or outside range", "Index number: " + t.ToInt32(Thread.CurrentThread.CurrentCulture).ToString()); 

      System.Diagnostics.Debug.WriteLine(property.Name + " is empty or outside range", "Index number: " + t.ToInt32(Thread.CurrentThread.CurrentCulture).ToString()); 
     } 
    } 
    else 
    { 
     logBuilder("Common.DisplayAll", "Info", "", property.Name + " is not defined in Enum", ""); 
     System.Diagnostics.Debug.WriteLine(property.Name + " is not defined in Enum"); 
    } 
    } 
    catch (Exception ex) 
    { 
     logBuilder("Common.DisplayAll", "Error", "", ex.Message, ""); 
     emailer.exceptionEmail(ex); 
     System.Diagnostics.Debugger.Break(); 
    } 

    System.Diagnostics.Debug.WriteLine("Name: " + property.Name + ", Value: " + property.GetValue(obj, null)); 
    } 
} 
catch (Exception ex) 
{ 
    logBuilder("Common.DisplayAll", "Error", "", ex.Message, ""); 
    emailer.exceptionEmail(ex); 
    System.Diagnostics.Debugger.Break(); 
    //throw; 
} 
return; 
} 

и назвать его, мы используем:

Common.DisplayAll<DCSSCustomerUpdate_V3>(wsSoapBody, aMessage); 
Смежные вопросы