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?

0


source to share


3 answers


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

+1


source


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());
    }
}

      

+1


source


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);

      

0


source







All Articles