2012-12-11 59 views
0

我正在使用specflow和selenium,並且我正在製作一個表來構建網站中的用戶輸入。使用枚舉和StringValue

| Input1 | Input2 | Input3 | 
| Opt1 | OptX | Opt2 | 

而且我爲輸入一個類:

public class ObjectDTO 
{ 
    public string Input1; 
    public Input2Type Input2; 
    public string Input3; 
} 

而對於一個特定選擇的枚舉(因爲它是一個靜態的輸入)

public enum Input2Type 
{ 
    [StringValue("OptX")] 
    X, 
    [StringValue("OptY")] 
    Y, 
    [StringValue("OptZ")] 
    Z 
} 

當我輸入我嘗試實例化對象:

ObjectDTO stocks = table.CreateInstance<ObjectDTO>(); 

但它說'沒有找到價值OptX的枚舉'。

+4

'OptX'是你提到的自定義屬性的值需要一個機制來匹配該值,並獲得相應的枚舉,這可能有助於http://stackoverflow.com/questions/10426444/enum-set-to-string-and-get-get-需要時刺痛值 – V4Vendetta

+0

表是什麼? –

+0

是specflow的一個類 - TechTalk.SpecFlow.Table –

回答

1

不幸的是,table.CreateInstance()是一個相當天真的方法,並失敗了枚舉(除其他外)。我最終編寫了一個表的擴展方法,它使用反射來詢問它正試圖創建的對象實例。這種方法的好處是該方法只會覆蓋表列中指定的實例值,但是,您必須爲表的每一行調用它並傳入已經實例化的實例。它可以很容易地修改行爲就像CreateInstance方法,但對於我而言,這更好地工作......

public static class TableExtensions 
{ 
    public static void FillInstance(this Table table, TableRow tableRow, object instance) { 
    var propertyInfos = instance.GetType().GetProperties(); 
    table.Header.Each(header => Assert.IsTrue(propertyInfos.Any(pi => pi.Name == header), "Expected to find the property [{0}] on the object of type [{1}]".FormatWith(header, instance.GetType().Name))); 
    var headerProperties = table.Header.Select(header => propertyInfos.Single(p => p.Name == header)).ToList(); 
    foreach (var propertyInfo in headerProperties) { 
     object propertyValue = tableRow[propertyInfo.Name]; 
     var propertyType = propertyInfo.PropertyType; 
     if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) { 
     propertyType = propertyType.GetGenericArguments().Single(); 
     } 

     var parse = propertyType.GetMethod("Parse", new[] { typeof(string) }); 
     if (parse != null) { 
     // ReSharper disable RedundantExplicitArrayCreation 
     try { 
      propertyValue = propertyType.Name.Equals("DateTime") ? GeneralTransformations.TranslateDateTimeFrom(propertyValue.ToString()) : parse.Invoke(null, new object[] { propertyValue }); 
     } catch (Exception ex) { 
      var message = "{0}\r\nCould not parse value: {2}.{3}(\"{1}\")".FormatWith(ex.Message, propertyValue, parse.ReturnType.FullName, parse.Name); 
      throw new Exception(message, ex); 
     } 
     // ReSharper restore RedundantExplicitArrayCreation 
     } 

     propertyInfo.SetValue(instance, propertyValue, null); 
    } 
    } 
} 

而且你可以按照以下方式調用它:

ObjectDTO objectDTO; 
foreach (var tableRow in table.Rows) 
{ 
    objectDTO = table.FillInstance(tableRow, new ObjectDTO()); 
    //Do individual row processing/testing here... 
}