2015-06-23 65 views
0

我正在創建一個日誌分析工具,即將CSV文件解析爲從根類派生的各個類。但是,定義各個類並在每個類中設置其各自的屬性需要很長時間,因爲有數百種不同類型的日誌。我注意到的事情是,這幾乎都是完全相同的東西,並想看看是否有辦法加快速度,並按照LINQ to DB如何操作並添加一些邏輯來自動設置基於來自Attributes的信息的屬性。在父類中使用自定義屬性設置子項屬性

下面是我正在使用的一個示例,以及關於應該如何工作的一個想法。

class Program 
{ 
    static void Main(string[] args) 
    { 
     Dictionary<string, string> dictionary = new Dictionary<string, string> 
     { 
      {"key", "Stack Overflow"}, 
      {"item1", "Test"}, 
      {"item2", "Sample"}, 
      {"item3", "3"} 
     }; 

     Example example = new Example(dictionary); 
     Console.WriteLine(example.LogKey); //Stack Overflow 
     Console.WriteLine(example.Item1); //Test 
     Console.WriteLine(example.Item2); // 
     Console.WriteLine(example.Item3); //3 
     Console.ReadKey(); 
    } 
} 

[AttributeUsage(AttributeTargets.Property)] 
class LogItem : Attribute 
{ 
    public LogItem(string key) 
    { 
     Key = key; 
    } 

    public string Key { get; private set; } 
    public bool Ignore { get; set; } 
} 

class Log 
{ 
    public Log(Dictionary<string, string> items) 
    { 
     Dictionary = items; 
    } 

    public Dictionary<string, string> Dictionary { get; private set; } 

    [LogItem("key")] 
    public string LogKey { get; set; } 
} 

class Example : Log 
{ 
    public Example(Dictionary<string, string> items) : base(items) 
    { 
    } 

    [LogItem("item1")] 
    public string Item1 { get; set; } 

    [LogItem("item2", Ignore = true)] 
    public string Item2 { get; set; } 

    [LogItem("item3")] 
    public int Item3 { get; set; } 
} 

我所有的數據將作爲字符串通過正在添加不幸所以這將是一個好主意,讓該屬性的類型和字符串轉換爲這一點。這個問題現在並不重要,因爲我可以自己做到這一點。

有沒有人有關於如何做這種工作的想法?如果可能的話,可以在父類中完成這樣的事情,以允許子類自己設置屬性Ignore == true

+0

你可以使用反射來設置屬性,但是如果你已經有'Dictionary',爲什麼你真的需要屬性? 'Example'類的用法是什麼?爲什麼不保留'Dictionary'?而且,對於屬性來說,它並不是很清楚(對我?)。 CSV - >字典,完美,無需上課。 – Sinatr

回答

0

目標屬性我能想出尋找到LINQ到CSV如何工作後,下面的。

static void ExtractData(Log log) 
{ 
    List<PropertyInfo> propertyInfos = 
     log.GetType() 
      .GetProperties() 
      .Where(
       p => p.GetCustomAttributes(typeof (LogItem), true).Any(logItem => !((LogItem) logItem).Ignore)) 
      .ToList(); 

    foreach (var propertyInfo in propertyInfos) 
    { 
     LogItem logItem = (LogItem)propertyInfo.GetCustomAttributes(typeof(LogItem), true).First(); 

     if(!log.Dictionary.ContainsKey(logItem.Key)) 
      continue; 

     TypeConverter typeConverter = TypeDescriptor.GetConverter(propertyInfo.PropertyType); 
     MethodInfo parseNumberMethod = propertyInfo.PropertyType.GetMethod("Parse", 
      new[] { typeof(String), typeof(NumberStyles), typeof(IFormatProvider) }); 
     MethodInfo parseExactMethod = propertyInfo.PropertyType.GetMethod("ParseExact", 
      new[] { typeof(string), typeof(string), typeof(IFormatProvider) }); 

     Object objValue = null; 

     if (typeConverter.CanConvertFrom(typeof(string))) 
     { 
      objValue = typeConverter.ConvertFromString(null, CultureInfo.CurrentCulture, log.Dictionary[logItem.Key]); 
      Debug.WriteLine("TypeConverter - " + propertyInfo.Name); 
     } 
     else if (parseExactMethod != null) 
     { 
      objValue = 
       parseExactMethod.Invoke(
        propertyInfo.PropertyType, 
        new Object[] 
         { 
          log.Dictionary[logItem.Key], 
          logItem.OutputFormat, 
          CultureInfo.CurrentCulture 
         }); 
     } 
     else if (parseNumberMethod != null) 
     { 
      objValue = 
       parseNumberMethod.Invoke(
        propertyInfo.PropertyType, 
        new Object[] 
         { 
          log.Dictionary[logItem.Key], 
          logItem.NumberStyles, 
          CultureInfo.CurrentCulture 
         }); 
     } 
     else 
     { 
      objValue = log.Dictionary[logItem.Key]; 
     } 

     PropertyInfo goodPropertyInfo = propertyInfo.DeclaringType.GetProperty(propertyInfo.Name); 
     goodPropertyInfo.SetValue(log, objValue, null); 
    } 
} 
0

你見過LinqToCSV嗎?您可以爲每種類型的日誌創建類,添加繼承等,並使用屬性描述列。

這裏是一個簡單的代碼將變得如此簡單的例子。

IEnumerable<ManualInputFormat> MapFileToRows(Stream input) 
{ 
    var csvDescriptor = new CsvFileDescription 
          { 
           SeparatorChar = ',', 
           FirstLineHasColumnNames = true 
          }; 

    var context = new CsvContext(); 
    return context.Read<InputFormat>(new StreamReader(input), csvDescriptor); 
} 

其中InputFormat是你的裝飾POCO

http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library

+1

OP想要CSV。並且鏈接唯一的答案不是很受歡迎(考慮從那裏發佈重要的關鍵部分)。 – Sinatr

+0

雖然我同意鏈接唯一的答案。這個頁面已經有相當長的一段時間了(2008),並且我在生產中多次使用這個解決方案。如果頁面被刪除,那麼可能會有更好的解決方案,因此這個答案已經過時。 – Mark