Hi have created this method to read from 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;
}
}
I call this method in other class like this:
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
}
The stringTable and r are set when the method is called but the dict I wanted to be set when I call ExcelReader
like this somehow:
private async Task OnFilesDropped(FileUploadModel upload)
{
var dict = new Dictionary<int, TreeItemModel>();
OfficeHelper.ExcelExtension.ExcelReader(upload, () => ExcelToProjTree(dict));
}
Is it possible? if yes, how?
CodePudding user response:
Since you'll be supplying a static object
parameter argument (this is known as partial application btw), you'll want to remove that from the parameter list of the resulting Func
type:
public static Dictionary<int, TreeItemModel> ExcelReader(FileUploadModel upload,
Func<Dictionary<int, string>, Row, Action> func) { /* */ }
Then make sure the lambda you supply as an argument to ExcelReader
has the correct signature as well (it should still accept Dictionary<int, string>
and Row
arguments):
OfficeHelper.ExcelExtension.ExcelReader(upload, (stringTable, row) => ExcelToProjTree(stringTable, row, dict));
And finally update the invocation of the function so that you only pass the first two parameter arguments:
func(stringTable, r); // `dict` will automatically be bound inside of `func`
Given that func
still returns an Action
, you might want to invoke that right away:
func(stringTable, r)();
CodePudding user response:
You can use 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);
}