我正在创建一个Log Parsing工具,即将CSV文件解析为从根类派生的各个类。但是,由于存在数百种不同类型的日志,因此定义各个类并在每个类中设置各自的属性需要很长时间。我注意到的事情是它几乎都是完全相同的东西,并想看看是否有办法加快速度并做一些LINQ to DB如何做事情并添加一些逻辑来自动设置基于属性信息的属性。
以下是我正在使用的一个示例,以及有关如何运作的想法。
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 :(得分: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 :(得分:0)
在研究了LINQ to 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);
}
}