C# 传递多个属性作为流体记录的参数
C# passing multiple properties as parameters for fluid logging
我正在尝试将多个属性传递给一种无缝记录的方法。我正在遍历文件列表并希望根据属性值记录它们。目前,我正在使用 enum
和 bool
属性,但我可以想象将来需要使用其他参数。
public enum MyTypes {
Type1,
Type2,
Type3
}
public class MyFile {
public string Filename { get; set; }
public bool ClassBool { get; set; }
public MyTypes Type { get; set; }
}
如果没有这种优化,该方法将必须包含每次比较的循环:
public void LogFiles(List<MyFile> files) {
logger.Info("--- Begin Type1 Print ---\n\n");
for (int i = 0; i < files.Count; i++) {
if (files[i].Type == MyTypes.Type1)
logger.Info(files[i].Filename);
}
logger.Info("--- End Type1 Print ---\n\n");
logger.Info("--- Begin Type2 Print ---\n\n");
for (int i = 0; i < files.Count; i++) {
if (files[i].Type == MyTypes.Type2)
logger.Info(files[i].Filename);
}
logger.Info("--- End Type2 Print ---\n\n");
logger.Info("--- Begin Class Bool Print ---\n\n");
for (int i = 0; i < files.Count; i++) { //Example of not passing the same param
if (ClassBool == true)
logger.Info(files[i].Filename);
}
logger.Info("--- End Class Bool Print ---\n\n");
}
我想传递文件、日志消息(可能与 属性 的名称不同)和 属性。我想我还必须传递某种委托,但我还不知道该怎么做。我想象类似这样的东西(不确定如何准确编码,所以它只是指导性的伪代码):
public void LogFiles(List<MyFile> files, string message, PropertyInfo prop, Delegate<UnsureHere> del)
logger.Info($"--- Begin {message} Print ---\n\n");
for (int i = 0; i < files.Count; i++) {
if (/*may use delegate here*/)
logger.Info(/*access property*/);
}
logger.Info($"--- End {message} Print ---\n\n");
}
所有这些都是为了实现这样的用例:
List<MyFile> files = new();
LogFiles(files, "Type1", /*not sure how to pass these*/);
LogFiles(files, "Type2", /*not sure how to pass these*/);
LogFiles(files, "Class Bool", /*not sure how to pass these*/);
我知道用一个循环和一个 switch 语句可以实现类似的东西,但我喜欢上面的代码产生的格式。这可能吗?感谢您的帮助!
您可以添加一些动态函数参数来实现您的目标。您需要两个动态函数:
一个到 return 基于 MyFile 内容的布尔值,它将控制信息是否被记录 Func<MyFile, bool> includeSelector
另外一个要return要记录的字符串数据Func<MyFile, string> dataSelector
您可以像这样实现上面的内容:
public void LogFiles(
List<MyFile> files,
string message,
Func<MyFile, bool> includeSelector,
Func<MyFile, string> dataSelector
)
{
logger.Info($"--- Begin {message} Print ---\n\n");
for (int i = 0; i < files.Count; i++)
{
if (includeSelector(files[i]))
logger.Info(dataSelector(files[i]));
}
logger.Info($"--- End {message} Print ---\n\n");
}
使用 LINQ,您可以将其缩短为:
public void LogFiles(
List<MyFile> files,
string message,
Func<MyFile, bool> includeSelector,
Func<MyFile, string> dataSelector
)
{
logger.Info($"--- Begin {message} Print ---\n\n");
foreach (var file in files.Where(f => includeSelector(f)))
logger.Info(dataSelector(f);
logger.Info($"--- End {message} Print ---\n\n");
}
您可以使用
来调用它
LogFiles(files, "Type1", x => x.ClassBool, x => x.Filename);
x => x.ClassBool
是一个函数,它将在箭头的左侧采用 MyFile 参数,return 在右侧采用操作结果。请注意,您的代码中没有声明实际变量 x;我只是选择将其用作该动态函数的变量名。
这与 LINQ 表达式的思路相同。
我正在尝试将多个属性传递给一种无缝记录的方法。我正在遍历文件列表并希望根据属性值记录它们。目前,我正在使用 enum
和 bool
属性,但我可以想象将来需要使用其他参数。
public enum MyTypes {
Type1,
Type2,
Type3
}
public class MyFile {
public string Filename { get; set; }
public bool ClassBool { get; set; }
public MyTypes Type { get; set; }
}
如果没有这种优化,该方法将必须包含每次比较的循环:
public void LogFiles(List<MyFile> files) {
logger.Info("--- Begin Type1 Print ---\n\n");
for (int i = 0; i < files.Count; i++) {
if (files[i].Type == MyTypes.Type1)
logger.Info(files[i].Filename);
}
logger.Info("--- End Type1 Print ---\n\n");
logger.Info("--- Begin Type2 Print ---\n\n");
for (int i = 0; i < files.Count; i++) {
if (files[i].Type == MyTypes.Type2)
logger.Info(files[i].Filename);
}
logger.Info("--- End Type2 Print ---\n\n");
logger.Info("--- Begin Class Bool Print ---\n\n");
for (int i = 0; i < files.Count; i++) { //Example of not passing the same param
if (ClassBool == true)
logger.Info(files[i].Filename);
}
logger.Info("--- End Class Bool Print ---\n\n");
}
我想传递文件、日志消息(可能与 属性 的名称不同)和 属性。我想我还必须传递某种委托,但我还不知道该怎么做。我想象类似这样的东西(不确定如何准确编码,所以它只是指导性的伪代码):
public void LogFiles(List<MyFile> files, string message, PropertyInfo prop, Delegate<UnsureHere> del)
logger.Info($"--- Begin {message} Print ---\n\n");
for (int i = 0; i < files.Count; i++) {
if (/*may use delegate here*/)
logger.Info(/*access property*/);
}
logger.Info($"--- End {message} Print ---\n\n");
}
所有这些都是为了实现这样的用例:
List<MyFile> files = new();
LogFiles(files, "Type1", /*not sure how to pass these*/);
LogFiles(files, "Type2", /*not sure how to pass these*/);
LogFiles(files, "Class Bool", /*not sure how to pass these*/);
我知道用一个循环和一个 switch 语句可以实现类似的东西,但我喜欢上面的代码产生的格式。这可能吗?感谢您的帮助!
您可以添加一些动态函数参数来实现您的目标。您需要两个动态函数:
一个到 return 基于 MyFile 内容的布尔值,它将控制信息是否被记录
Func<MyFile, bool> includeSelector
另外一个要return要记录的字符串数据
Func<MyFile, string> dataSelector
您可以像这样实现上面的内容:
public void LogFiles(
List<MyFile> files,
string message,
Func<MyFile, bool> includeSelector,
Func<MyFile, string> dataSelector
)
{
logger.Info($"--- Begin {message} Print ---\n\n");
for (int i = 0; i < files.Count; i++)
{
if (includeSelector(files[i]))
logger.Info(dataSelector(files[i]));
}
logger.Info($"--- End {message} Print ---\n\n");
}
使用 LINQ,您可以将其缩短为:
public void LogFiles(
List<MyFile> files,
string message,
Func<MyFile, bool> includeSelector,
Func<MyFile, string> dataSelector
)
{
logger.Info($"--- Begin {message} Print ---\n\n");
foreach (var file in files.Where(f => includeSelector(f)))
logger.Info(dataSelector(f);
logger.Info($"--- End {message} Print ---\n\n");
}
您可以使用
来调用它LogFiles(files, "Type1", x => x.ClassBool, x => x.Filename);
x => x.ClassBool
是一个函数,它将在箭头的左侧采用 MyFile 参数,return 在右侧采用操作结果。请注意,您的代码中没有声明实际变量 x;我只是选择将其用作该动态函数的变量名。
这与 LINQ 表达式的思路相同。