通常填充不同的类成员

时间:2015-01-27 11:04:45

标签: c# .net class system.reflection

我正在开发一个包含多个(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,
    ...
}

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

部分类在wsdl中定义如下:

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

而不是分别为每一个(在11个自定义服务类中的每一个中)执行此操作,我想知道有没有办法传入分部类 wsSoapBody (沿着使用字符串数组)并循环遍历类的所有成员,从字符串数组中分配值?

修改

我搜索并找到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 ...

那我该去哪里?

3 个答案:

答案 0 :(得分:1)

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

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

所以你有这个枚举DCSSCustomerUpdate_V3哪些成员匹配wsSoapBody类的属性名称,你不想像上面那样重复代码,但是使用循环,对吗? / p>

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

答案 1 :(得分:1)

试试

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

您还可以使用方法Enum.TryParse

对于通用枚举类型或多或少如此

 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

答案 2 :(得分:0)

所以感谢FabioSloth,这是我们构建的最终代码:

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