3

I am building a Soap Body for a web-service, and there are dozens of optional fields.

Currently I have been handling these like this:

wsSoapBody.OrderType = aMessage[(int)cardCreate.OrderType].ToString();
wsSoapBody.ActivateFlag = Convert.ToInt32(aMessage[(int)cardCreate.ActivateFlag].ToString()); //P-02925;

if (aMessage[(int)cardCreate.ShipDate].ToString() != ""){
                wsSoapBody.ShipmentDate = Convert.ToDateTime(aMessage[(int)cardCreate.ShipDate].ToString()); //P-02925;
        }

wsSoapBody.ShipmentMethodCard = aMessage[(int)cardCreate.ShipMethodCard].ToString();
wsSoapBody.ShipmentMethodPin = aMessage[(int)cardCreate.ShipMethodPIN].ToString();

The CardCreate you see in those value assignments is an enumerated constant in the class cardCreate defined as below:

namespace EvryCardManagement
{
    class CardCreate
    {
        #region Variables

        private DCSSCardCreateType req;
        private DCSSCardCreateResponseType rsp;
        private DCSSCardCreate_V3_0Service stub;

        public string tokenID { get; set; }

        private enum cardCreate
        {
            MsgType = 0,
            MsgVersion = 1,
            WSName = 2,
            ReplyTo = 3,
            SourceSystem = 4,
            Timestamp = 5,
            UniqueMessageID = 6,
            SFDCContext = 7,
            InstitutionID = 8,
            CardNumber = 9,
            Version = 10,
            ProductID = 11,
            AccountNumber = 12,
            CustomerID = 13,
            CustomerNumber = 14,
            EmbossName1 = 15,
            Expiry = 16,
            FeeMonth = 17,
            ChargeAccountNo = 18,
            PINMethod = 19,
            CardFlag = 20,
            AddressTypeCard = 21,
            AddressTypePIN = 22,
            OrderType = 23,
            ActivateFlag = 24,
            ShipDate = 25,
            ShipMethodCard = 26,
            ShipMethodPIN = 27,
            FirstName = 28,
            LastName = 29,
            CardAddress1 = 30,
            CardAddress2 = 31,
            CardAddress3 = 32,
            CardAddress4 = 33,
            CardAddress5 = 34,
            CardAddress6 = 35,
            CardPostCode = 36,
            CardCity = 37,
            CardCountry = 38,
            PINName = 39,
            PINAddress1 = 40,
            PINAddress2 = 41,
            PINAddress3 = 42,
            PINAddress4 = 43,
            PINAddress5 = 44,
            PINAddress6 = 45,
            PINPostCode = 46,
            PINCity = 47,
            PINCountry = 48,
            Validfrom = 49,
            Note = 50,
            MakeCheckStatus = 51,
            EmbossName2 = 52,
            PAmount = 53,
            PAmountLength = 54,
            GKIndicator = 55,
            CreditLimit = 56,
            CardDesignNo = 57,
            ExtPictureID = 58,
            BulkID = 59,
            AccountNo2 = 60
        }

so, rather than doing them all one by one as I have been doing, is it possible to loop through the wsSoapBody (which is defined in the web-service) and for each one, get the corresponding value from the aMessage (which is defined as an array like this string[] aMessage)

EDIT

I have the below code to loop through, but I want to assign to the wsSoapBody and I am stuck:

foreach (cardCreate cItem in (cardCreate[])Enum.GetValues(typeof(cardCreate)))
 {
 }

(the above correction was suggested as an edit by Steve Lillis that was rejected due to a conflict)

so I don't know how then to assign the values to each element for example I want to set

wsSoapBody[cItem].value = aMessage[(int)CardCreate[cItem]` 

or I also tried:

wsSoapBody[cItem] = aMessage[(int)cItem].ToString();

but am having trouble making it work (or even compile) due to lack of knowledge

EDIT #2:

I have also looked at GetNames as possibly I want the names and tried:

        foreach (string name in Enum.GetNames(typeof(cardCreate)))

        {
            wsSoapBody[name] = aMessage[(int)name].ToString();
        }

But I cannot apply indexing with [] to an expression of type 'DCSSCardCreateType'

thanks

8
  • 4
    Have you looked at Enum.GetValues? Commented Jan 8, 2015 at 16:42
  • possible duplicate of Can You Loop Through All Enum Values? Commented Jan 8, 2015 at 16:45
  • Hi Jon, yes, I have used foreach (cardCreate cItem in (cardCreate[])Enum.GetValues(typeof(cardCreate))) { } BUT I don't know how then to assign the values to each element for example I want to set wsSoapBody[cItem].value = aMessage[(int)CardCreate[cItem] but am having strouble making it work Commented Jan 8, 2015 at 16:46
  • I am editing the question, I see that it isn't clear that I can get some of the way, but am having trouble assigning the values... Commented Jan 8, 2015 at 16:48
  • @CompuChip: I have edited the question and title to clarify that I have the enumerated loop but don't know how to assign values from my string array Commented Jan 8, 2015 at 16:52

1 Answer 1

3

Why not place the values onto the enum itself and then enumerate?

For example using System.ComponentModel Description attribute we can add that information to the enum itself such as:

public enum cardCreate
{
  [Description("General Response")]
  MsgType = 0,

  [Description("V2.0")]
  WSName = 2,

  [Description("OmegaMan")]
  ReplyTo = 3,

  [Description("Windows 10")]
  SourceSystem = 4,
}

So when we call a special method to enumerate the enum where we can extract that text and use it appropriately later such as:

myextensions.GetEnumValues<cardCreate>()
            .Select (ceEnum => new
                        {
                            Original   = ceEnum,
                            IndexValue = (int)ceEnum,
                            Text       = ceEnum.GetAttributeDescription()
                        })

The dynamic entity will look like this after the projection (the select):

enter image description here

Sweet! Now we have all the information in a easy consumable entity which provides all the information needed.

What? You need more than a string description? Then create a custom attribute on the enum and have all items/types of data to return as needed. For that see my blog article C# Using Extended Attribute Information on Objects.


Here are the extension methods used in the above example:

public static class myextensions
{
   public static IEnumerable<T> GetEnumValues<T>()
   {
       Type type = typeof( T );

       if (!type.IsEnum)
           throw new Exception( string.Format("{0} is not an enum.", type.FullName ));

       FieldInfo[] fields =
           type.GetFields( BindingFlags.Public | BindingFlags.Static );


       foreach (var item in fields)
           yield return (T)item.GetValue( null );
   }


  /// <summary>If an attribute on an enumeration exists, this will return that
   /// information</summary>
   /// <param name="value">The object which has the attribute.</param>
   /// <returns>The description string of the attribute or string.empty</returns>
   public static string GetAttributeDescription( this object value )
   {
       string retVal = string.Empty;
       try
       {
           retVal = value.GetType()
                         .GetField( value.ToString() )
                         .GetCustomAttributes( typeof( DescriptionAttribute ), false )
                         .OfType<DescriptionAttribute>()
                         .First()
                         .Description;

       }
       catch (NullReferenceException)
       {
           //Occurs when we attempt to get description of an enum value that does not exist
       }
       finally
       {
           if (string.IsNullOrEmpty( retVal ))
               retVal = "Unknown";
       }

       return retVal;
   }

}
Sign up to request clarification or add additional context in comments.

7 Comments

I don't know if this is the exact answer that I want, but you put the work in, and it will probably do what I need, so thanks!
So if I implement this how could I loop through my wsSoapBody class setting all the values from my aMessage[] array of string values?
@OurManInBananas you would need to reflect off the instance and beforehand provide a mapping to the enum which you then could gather the values.
yes that was what I was really asking in my question, or should I ask a new question for that? We have 12 web-services similar to cardCreate and they all have this problem where I need to set dozens of optional and mandatory fields in the wsSoapBody, so was looking for a way to re-use the same method for each one of them...
@OurManInBananas I would ask a different question, for it will give you the freedom to illicit responses geared to the final answer.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.