C# 传递多个属性作为流体记录的参数

C# passing multiple properties as parameters for fluid logging

我正在尝试将多个属性传递给一种无缝记录的方法。我正在遍历文件列表并希望根据属性值记录它们。目前,我正在使用 enumbool 属性,但我可以想象将来需要使用其他参数。

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 表达式的思路相同。