基于 PropertyInfo 名称过滤
Filtering based on PropertyInfo Name
我正在尝试修改以下代码:
public static string ToCsv<T>(this IEnumerable<T> list, List<string> keyIndicators, List<string> inTreatmentCohort)
{
var type = typeof(T);
var props = type.GetProperties();
//Setup expression constants
var param = Expression.Parameter(type, "x");
var doublequote = Expression.Constant("\"");
var doublequoteescape = Expression.Constant("\"\"");
var comma = Expression.Constant(",");
//Convert all properties to strings, escape and enclose in double quotes
var propq = (from prop in props
let tostringcall = Expression.Call(Expression.Property(param, prop),
prop.ReflectedType.GetMethod("ToString", new Type[0]))
let replacecall = Expression.Call(tostringcall,
typeof(string).GetMethod("Replace", new[] {typeof(string), typeof(string)}), doublequote,
doublequoteescape)
select Expression.Call(
typeof(string).GetMethod("Concat", new[] {typeof(string), typeof(string), typeof(string)}),
doublequote, replacecall, doublequote)
).ToArray();
var concatLine = propq[0];
for (var i = 1; i < propq.Length; i++)
concatLine =
Expression.Call(
typeof(string).GetMethod("Concat", new[] {typeof(string), typeof(string), typeof(string)}),
concatLine, comma, propq[i]);
var method = Expression.Lambda<Func<T, string>>(concatLine, param).Compile();
var header = string.Join(",", props.Select(p => p.Name).ToArray());
return header + Environment.NewLine + string.Join(Environment.NewLine, list.Select(method).ToArray());
}
我需要根据两个列表(keyIndicators 和 inTreatmentCohort)进行过滤,这两个列表包含正在转换为 CSV 的列表中包含的 PropertyInfo 名称字段的后缀和前缀。
我尝试添加一个 where keyIndicators.Contains(prop.Name) 本质上模拟一个 IN 语句 this returns null.
我还尝试将 propq 查询放在 foreach 循环中,这带来了正确的数据,但显示了所有列名,而不仅仅是在 keyIndicators 或 inTreatmentCohort 列表中选择的列名。
如何将此代码修改为仅 return 包含两个过滤列表中的列的 csv,而不是要转换的列表中的所有列?
已修改以包含新的 linq 查询
修改了我之前提供的代码 Contains 现在可以按预期工作,这些更改如下所示:
public static string ToCsv<T>(this IEnumerable<T> list, List<string> keyIndicators,
List<string> inTreatmentCohorts)
{
var type = typeof(T);
var props = type.GetProperties();
//Setup expression constants
var param = Expression.Parameter(type, "x");
var doublequote = Expression.Constant("\"");
var doublequoteescape = Expression.Constant("\"\"");
var comma = Expression.Constant(",");
MethodCallExpression[] propq = { };
var propqList = new List<MethodCallExpression>();
//Convert all properties to strings, escape and enclose in double quotes
foreach (var keyIndicator in keyIndicators)
{
if (keyIndicator != "Pend" && keyIndicator != "Area" && keyIndicator != "DrugGroup" &&
keyIndicator != "Gender") continue;
propq = (from prop in props
let tostringcall = Expression.Call(Expression.Property(param, prop),
prop.ReflectedType.GetMethod("ToString", new Type[0]))
let replacecall = Expression.Call(tostringcall,
typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) }), doublequote,
doublequoteescape)
where prop.Name.Contains(keyIndicator)
select Expression.Call(
typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), typeof(string) }),
doublequote, replacecall, doublequote)
).ToArray();
propqList.AddRange(propq);
}
foreach (var keyIndicator in keyIndicators)
{
foreach (var inTreatmentCohort in inTreatmentCohorts)
{
propq = (from prop in props
let tostringcall = Expression.Call(Expression.Property(param, prop),
prop.ReflectedType.GetMethod("ToString", new Type[0]))
let replacecall = Expression.Call(tostringcall,
typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) }),
doublequote,
doublequoteescape)
where prop.Name.Contains(inTreatmentCohort) && prop.Name.Contains(keyIndicator)
select Expression.Call(
typeof(string).GetMethod("Concat",
new[] { typeof(string), typeof(string), typeof(string) }),
doublequote, replacecall, doublequote)
).ToArray();
}
propqList.AddRange(propq);
}
propq = propqList.ToArray();
var concatLine = propq[0];
for (var i = 1; i < propq.Length; i++)
concatLine =
Expression.Call(
typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), typeof(string) }),
concatLine, comma, propq[i]);
var method = Expression.Lambda<Func<T, string>>(concatLine, param).Compile();
var header = string.Join(",", props.Select(p => p.Name).ToArray());
return header + Environment.NewLine + string.Join(Environment.NewLine, list.Select(method).ToArray());
}
我需要为 var header 重写 LINQ 查询,以便在生成 csv 时只显示在 propq 中选择的列。
尝试以下操作:
string[] columnNames = { "A", "B", "C", "D" };
string[] filteredColumns = { "A", "C", "D" };
string[] csv = {
"1,2,3,4",
"11,12,13,14",
"21,22,23,24",
"31,32,33,34"
};
int[] indexes = columnNames.Select((x, i) => new { x = x, i = i }).Where(x => filteredColumns.Contains(x.x)).Select(x => x.i).ToArray();
var results = csv.Select(x => x.Split(new char[] { ',' }).Where((y, i) => indexes.Contains(i)).ToArray()).ToArray();
进行一些修改后,我设法让 Contains 与几个 foreach 循环一起工作,以处理两个过滤器列表。
完整代码如下:
public static string ToCsv<T>(this IEnumerable<T> list, List<string> keyIndicators,
List<string> inTreatmentCohorts)
{
var type = typeof(T);
var props = type.GetProperties();
//Setup expression constants
var param = Expression.Parameter(type, "x");
var doublequote = Expression.Constant("\"");
var doublequoteescape = Expression.Constant("\"\"");
var comma = Expression.Constant(",");
MethodCallExpression[] propq = { };
var propqList = new List<MethodCallExpression>();
var columnNames = new List<string>();
//Convert all properties to strings, escape and enclose in double quotes
foreach (var keyIndicator in keyIndicators)
{
foreach (var inTreatmentCohort in inTreatmentCohorts)
{
propq = (from prop in props
let tostringcall = Expression.Call(Expression.Property(param, prop),
prop.ReflectedType.GetMethod("ToString", new Type[0]))
let replacecall = Expression.Call(tostringcall,
typeof(string).GetMethod("Replace", new[] {typeof(string), typeof(string)}), doublequote,
doublequoteescape)
where prop.Name.Contains(keyIndicator) && prop.Name.Contains(inTreatmentCohort)
select Expression.Call(
typeof(string).GetMethod("Concat", new[] {typeof(string), typeof(string), typeof(string)}),
doublequote, replacecall, doublequote)
).ToArray();
var columnNameQuery = (from prop in props
where prop.Name.Contains(keyIndicator) && prop.Name.Contains(inTreatmentCohort)
select prop.Name);
columnNames.AddRange(columnNameQuery);
propqList.AddRange(propq);
}
}
propq = propqList.ToArray();
var concatLine = propq[0];
for (var i = 1; i < propq.Length; i++)
concatLine =
Expression.Call(
typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), typeof(string) }),
concatLine, comma, propq[i]);
var method = Expression.Lambda<Func<T, string>>(concatLine, param).Compile();
var header = string.Join(",", columnNames.ToArray());
return header + Environment.NewLine + string.Join(Environment.NewLine, list.Select(method).ToArray());
}
我希望包含在 CSV 中的列名被添加到 columnNames 列表,然后被添加到 header 变量,以便列和数据在 CSV 中匹配。
我正在尝试修改以下代码:
public static string ToCsv<T>(this IEnumerable<T> list, List<string> keyIndicators, List<string> inTreatmentCohort)
{
var type = typeof(T);
var props = type.GetProperties();
//Setup expression constants
var param = Expression.Parameter(type, "x");
var doublequote = Expression.Constant("\"");
var doublequoteescape = Expression.Constant("\"\"");
var comma = Expression.Constant(",");
//Convert all properties to strings, escape and enclose in double quotes
var propq = (from prop in props
let tostringcall = Expression.Call(Expression.Property(param, prop),
prop.ReflectedType.GetMethod("ToString", new Type[0]))
let replacecall = Expression.Call(tostringcall,
typeof(string).GetMethod("Replace", new[] {typeof(string), typeof(string)}), doublequote,
doublequoteescape)
select Expression.Call(
typeof(string).GetMethod("Concat", new[] {typeof(string), typeof(string), typeof(string)}),
doublequote, replacecall, doublequote)
).ToArray();
var concatLine = propq[0];
for (var i = 1; i < propq.Length; i++)
concatLine =
Expression.Call(
typeof(string).GetMethod("Concat", new[] {typeof(string), typeof(string), typeof(string)}),
concatLine, comma, propq[i]);
var method = Expression.Lambda<Func<T, string>>(concatLine, param).Compile();
var header = string.Join(",", props.Select(p => p.Name).ToArray());
return header + Environment.NewLine + string.Join(Environment.NewLine, list.Select(method).ToArray());
}
我需要根据两个列表(keyIndicators 和 inTreatmentCohort)进行过滤,这两个列表包含正在转换为 CSV 的列表中包含的 PropertyInfo 名称字段的后缀和前缀。
我尝试添加一个 where keyIndicators.Contains(prop.Name) 本质上模拟一个 IN 语句 this returns null.
我还尝试将 propq 查询放在 foreach 循环中,这带来了正确的数据,但显示了所有列名,而不仅仅是在 keyIndicators 或 inTreatmentCohort 列表中选择的列名。
如何将此代码修改为仅 return 包含两个过滤列表中的列的 csv,而不是要转换的列表中的所有列?
已修改以包含新的 linq 查询
修改了我之前提供的代码 Contains 现在可以按预期工作,这些更改如下所示:
public static string ToCsv<T>(this IEnumerable<T> list, List<string> keyIndicators,
List<string> inTreatmentCohorts)
{
var type = typeof(T);
var props = type.GetProperties();
//Setup expression constants
var param = Expression.Parameter(type, "x");
var doublequote = Expression.Constant("\"");
var doublequoteescape = Expression.Constant("\"\"");
var comma = Expression.Constant(",");
MethodCallExpression[] propq = { };
var propqList = new List<MethodCallExpression>();
//Convert all properties to strings, escape and enclose in double quotes
foreach (var keyIndicator in keyIndicators)
{
if (keyIndicator != "Pend" && keyIndicator != "Area" && keyIndicator != "DrugGroup" &&
keyIndicator != "Gender") continue;
propq = (from prop in props
let tostringcall = Expression.Call(Expression.Property(param, prop),
prop.ReflectedType.GetMethod("ToString", new Type[0]))
let replacecall = Expression.Call(tostringcall,
typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) }), doublequote,
doublequoteescape)
where prop.Name.Contains(keyIndicator)
select Expression.Call(
typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), typeof(string) }),
doublequote, replacecall, doublequote)
).ToArray();
propqList.AddRange(propq);
}
foreach (var keyIndicator in keyIndicators)
{
foreach (var inTreatmentCohort in inTreatmentCohorts)
{
propq = (from prop in props
let tostringcall = Expression.Call(Expression.Property(param, prop),
prop.ReflectedType.GetMethod("ToString", new Type[0]))
let replacecall = Expression.Call(tostringcall,
typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) }),
doublequote,
doublequoteescape)
where prop.Name.Contains(inTreatmentCohort) && prop.Name.Contains(keyIndicator)
select Expression.Call(
typeof(string).GetMethod("Concat",
new[] { typeof(string), typeof(string), typeof(string) }),
doublequote, replacecall, doublequote)
).ToArray();
}
propqList.AddRange(propq);
}
propq = propqList.ToArray();
var concatLine = propq[0];
for (var i = 1; i < propq.Length; i++)
concatLine =
Expression.Call(
typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), typeof(string) }),
concatLine, comma, propq[i]);
var method = Expression.Lambda<Func<T, string>>(concatLine, param).Compile();
var header = string.Join(",", props.Select(p => p.Name).ToArray());
return header + Environment.NewLine + string.Join(Environment.NewLine, list.Select(method).ToArray());
}
我需要为 var header 重写 LINQ 查询,以便在生成 csv 时只显示在 propq 中选择的列。
尝试以下操作:
string[] columnNames = { "A", "B", "C", "D" };
string[] filteredColumns = { "A", "C", "D" };
string[] csv = {
"1,2,3,4",
"11,12,13,14",
"21,22,23,24",
"31,32,33,34"
};
int[] indexes = columnNames.Select((x, i) => new { x = x, i = i }).Where(x => filteredColumns.Contains(x.x)).Select(x => x.i).ToArray();
var results = csv.Select(x => x.Split(new char[] { ',' }).Where((y, i) => indexes.Contains(i)).ToArray()).ToArray();
进行一些修改后,我设法让 Contains 与几个 foreach 循环一起工作,以处理两个过滤器列表。
完整代码如下:
public static string ToCsv<T>(this IEnumerable<T> list, List<string> keyIndicators,
List<string> inTreatmentCohorts)
{
var type = typeof(T);
var props = type.GetProperties();
//Setup expression constants
var param = Expression.Parameter(type, "x");
var doublequote = Expression.Constant("\"");
var doublequoteescape = Expression.Constant("\"\"");
var comma = Expression.Constant(",");
MethodCallExpression[] propq = { };
var propqList = new List<MethodCallExpression>();
var columnNames = new List<string>();
//Convert all properties to strings, escape and enclose in double quotes
foreach (var keyIndicator in keyIndicators)
{
foreach (var inTreatmentCohort in inTreatmentCohorts)
{
propq = (from prop in props
let tostringcall = Expression.Call(Expression.Property(param, prop),
prop.ReflectedType.GetMethod("ToString", new Type[0]))
let replacecall = Expression.Call(tostringcall,
typeof(string).GetMethod("Replace", new[] {typeof(string), typeof(string)}), doublequote,
doublequoteescape)
where prop.Name.Contains(keyIndicator) && prop.Name.Contains(inTreatmentCohort)
select Expression.Call(
typeof(string).GetMethod("Concat", new[] {typeof(string), typeof(string), typeof(string)}),
doublequote, replacecall, doublequote)
).ToArray();
var columnNameQuery = (from prop in props
where prop.Name.Contains(keyIndicator) && prop.Name.Contains(inTreatmentCohort)
select prop.Name);
columnNames.AddRange(columnNameQuery);
propqList.AddRange(propq);
}
}
propq = propqList.ToArray();
var concatLine = propq[0];
for (var i = 1; i < propq.Length; i++)
concatLine =
Expression.Call(
typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), typeof(string) }),
concatLine, comma, propq[i]);
var method = Expression.Lambda<Func<T, string>>(concatLine, param).Compile();
var header = string.Join(",", columnNames.ToArray());
return header + Environment.NewLine + string.Join(Environment.NewLine, list.Select(method).ToArray());
}
我希望包含在 CSV 中的列名被添加到 columnNames 列表,然后被添加到 header 变量,以便列和数据在 CSV 中匹配。