一般填充不同的 类 成员

Generically populate different classes members

我正在开发一个具有多个 (11) 网络服务调用的网络服务应用程序。

对于每个 Web 服务,我需要从这样的字符串数组填充 Soap 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,
    ...
}

部分 class 中的 属性 名称与枚举常量匹配,所以我想我也应该传入枚举常量?

部分class在wsdl中定义如下:

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

而不是对每个单独执行此操作(在 11 个自定义 serviceclasses 中的每一个中),我想知道是否有一种方法可以传递部分 class wsSoapBody(连同字符串数组)并遍历 class 的所有成员,从字符串数组赋值?

编辑:

我搜索并找到 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(); 不会编译 - 因为它正在寻找从枚举常量返回的 int...

那我该去哪里呢?

不知道我是否理解你的问题:

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

所以你有这个枚举 DCSSCustomerUpdate_V3 哪些成员匹配 wsSoapBody class 的 属性 名称,你不想重复代码以上,但使用循环,对吗?

您可以简单地遍历 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());
    }
}

试试看

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

看到这个postCreate Generic method constraining T to an Enum

感谢 Fabio and Sloth,这是我们构建的最终代码:

public static void DisplayAll<TEnum>(Object obj, string[] aMessage) where TEnum : struct,  IComparable, IFormattable, IConvertible
/* 
 * see 
 * 
 */
{
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);