C#传递带有参数的Func,传递时设置1个参数,其他设置在里面

C# passing Func with parameters where 1 parameter is set while passing and the others are set inside

你好创建了这个方法来读取 excel:

        public static Dictionary<int, TreeItemModel> ExcelReader(FileUploadModel upload,
            Func<Dictionary<int, string>, Row, object, Action> func)
        {
            try
            {
                var dict = new Dictionary<int, TreeItemModel>();
                using (var doc = SpreadsheetDocument.Open(upload.Stream, false))
                {
                    var workbookPart = doc.WorkbookPart;

                    var worksheetPart = workbookPart.WorksheetParts.First();

                    var sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();

                    var stringTable = LoadSharedStringDictionarySax(workbookPart.SharedStringTablePart);

                    foreach (var r in sheetData.Elements<Row>())
                    {
                        func(stringTable, r, dict);
                    }
                }

                upload.Stream.Close();

                upload.UploadCompletion = 100;

                return dict;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);

                throw;
            }
        }        

我在其他class中这样调用这个方法:

private async Task OnFilesDropped(FileUploadModel upload)
{
    var dict = new Dictionary<int, TreeItemModel>();

    OfficeHelper.ExcelExtension.ExcelReader(upload, ExcelToProjTree);
}

private static Action ExcelToProjTree(Dictionary<int, string> stringTable, Row r, Dictionary<int, TreeItemModel> dict)
{
  //Some stuff
}

调用方法时设置了stringTable和r,但我想在调用ExcelReader时设置dict

有点像这样:

private async Task OnFilesDropped(FileUploadModel upload)
{
    var dict = new Dictionary<int, TreeItemModel>();

    OfficeHelper.ExcelExtension.ExcelReader(upload, () => ExcelToProjTree(dict));
}

可能吗?如果是,怎么做?

您可以使用Lazy<T>

private Lazy<Dictionary<int, TreeItemModel>> dict;

// Constructor
public YourClass()
{
    this.dict = Lazy<Dictionary<int, TreeItemModel>>(
        () => ExcelToProjTree(new Dictionary<int, TreeItemModel>()));
}

private async Task OnFilesDropped(FileUploadModel upload)
{
    var dict = new Dictionary<int, TreeItemModel>();

    // ExcelToProjTree Will be eveluated only now
    OfficeHelper.ExcelExtension.ExcelReader(upload, () => dict.Value);
}

由于您将提供一个静态 object 参数参数(这被称为 partial application 顺便说一句),您需要将其从结果 [=15 的参数列表中删除=]类型:

public static Dictionary<int, TreeItemModel> ExcelReader(FileUploadModel upload,
        Func<Dictionary<int, string>, Row, Action> func) { /* */ }

然后确保作为参数提供给 ExcelReader 的 lambda 也具有正确的签名(它仍然应该接受 Dictionary<int, string>Row 参数):

OfficeHelper.ExcelExtension.ExcelReader(upload, (stringTable, row) => ExcelToProjTree(stringTable, row, dict));

最后更新函数的调用,以便您只传递前两个参数参数:

func(stringTable, r); // `dict` will automatically be bound inside of `func`

鉴于 func 仍然 returns 和 Action,您可能想立即调用它:

func(stringTable, r)();