Usually filled by different classes of participants
I am working on a web service application with multiple (11) web service calls.
For each webservice, I need to populate the soap body from an array of strings like this:
if (aMessage[(int)DCSSCustomerUpdate_V3.Branch].ToString().Length != 0)
{
wsSoapBody.Branch = aMessage[(int)DCSSCustomerUpdate_V3.Branch].ToString();
}
aMessage[int]
is a string array, and [int] is defined by an enumerated constant - in this case, it is defined as follows:
private enum DCSSCustomerUpdate_V3
{
MsgType = 0,
MsgVersion = 1,
WSName = 2,
ReplyTo = 3,
SourceSystem = 4,
...
}
Property names in a partial class are mapped to an enumerated constant, so I assume I would enumerate an enumerated constant too?
The partial class is defined in wsdl as follows:
public partial class DCSSCustomerUpdateType
{
private string instIdField;
private string branchField;
...
}
Rather than doing this for each one separately (in each of the 11 custom service classes), I'm wondering if there is a way to pass a partial wsSoapBody class (along with an array of strings) and loop through all the members of the class, assigning values ββfrom the array of strings?
EDIT
I searched and found SO: 531384 / how-to-loop-through-all-the-properties-of-a-class?
So I tried this:
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));
}
}
but string value = aMessage[property.Name].ToString();
won't compile - since it looks for an int returned from an enumerated constant ...
where can i go from there?
source to share
Try
DCSSCustomerUpdate_V3 t = (DCSSCustomerUpdate_V3)Enum.Parse(typeof(DCSSCustomerUpdate_V3), property.Name);
string value = aMessage[(int)t].ToString();
you can also use Enum.TryParse method
For a generic Enum type, more or less
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));
}
}
see this post Create Generic Method Constraining T to Enum
source to share
I don't know if I understood your question:
if (aMessage[(int)DCSSCustomerUpdate_V3.Branch].ToString().Length != 0)
{
wsSoapBody.Branch = aMessage[(int)DCSSCustomerUpdate_V3.Branch].ToString();
}
So you have this enum DCSSCustomerUpdate_V3
, whose members correspond to the class property names wsSoapBody
, and you don't want to repeat code like the above, but use a loop, right?
You can just loop over all the elements DCSSCustomerUpdate_V3
and set the property value like this:
// 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());
}
}
source to share
thanks to Fabio and Sloth , here is the final code we built:
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;
}
and to call it we use:
Common.DisplayAll<DCSSCustomerUpdate_V3>(wsSoapBody, aMessage);
source to share