Decompiled source of Divination Logger v1.2.0
BepInEx/plugins/MiniExcel.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Dynamic; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using Microsoft.CodeAnalysis; using MiniExcelLibs.Attributes; using MiniExcelLibs.Csv; using MiniExcelLibs.Exceptions; using MiniExcelLibs.OpenXml; using MiniExcelLibs.OpenXml.Constants; using MiniExcelLibs.OpenXml.Models; using MiniExcelLibs.OpenXml.SaveByTemplate; using MiniExcelLibs.OpenXml.Styles; using MiniExcelLibs.Utils; using MiniExcelLibs.WriteAdapter; using MiniExcelLibs.Zip; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("Mini-Software")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Wei Lin, 2021 onwards")] [assembly: AssemblyDescription("Fast, Low-Memory, Easy Excel .NET helper to import/export/template spreadsheet\r\nGithub : https://github.com/mini-software/MiniExcel\r\nGitee : https://gitee.com/dotnetchina/MiniExcel\r\nIssues : https://github.com/mini-software/MiniExcel/issues\r\nTodo : https://github.com/mini-software/MiniExcel/projects/1?fullscreen=true")] [assembly: AssemblyFileVersion("1.39.0.0")] [assembly: AssemblyInformationalVersion("1.39.0+177f86e4fe70324abbc343c51b5ce381537f9f77")] [assembly: AssemblyProduct("MiniExcel")] [assembly: AssemblyTitle("MiniExcel")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/mini-software/MiniExcel")] [assembly: NeutralResourcesLanguage("en")] [assembly: AssemblyVersion("1.39.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } namespace MiniExcelLibs { internal class ExcelReaderFactory { internal static IExcelReader GetProvider(Stream stream, ExcelType excelType, IConfiguration configuration) { return excelType switch { ExcelType.CSV => new CsvReader(stream, configuration), ExcelType.XLSX => new ExcelOpenXmlSheetReader(stream, configuration), _ => throw new NotSupportedException("Please Issue for me"), }; } } internal class ExcelWriterFactory { internal static IExcelWriter GetProvider(Stream stream, object value, string sheetName, ExcelType excelType, IConfiguration configuration, bool printHeader) { if (string.IsNullOrEmpty(sheetName)) { throw new InvalidDataException("Sheet name can not be empty or null"); } return excelType switch { ExcelType.UNKNOWN => throw new InvalidDataException("Please specify excelType"), ExcelType.CSV => new CsvWriter(stream, value, configuration, printHeader), ExcelType.XLSX => new ExcelOpenXmlSheetWriter(stream, value, sheetName, configuration, printHeader), _ => throw new NotSupportedException("Please Issue for me"), }; } } internal class ExcelTemplateFactory { internal static IExcelTemplateAsync GetProvider(Stream stream, IConfiguration configuration, ExcelType excelType = ExcelType.XLSX) { if (excelType == ExcelType.XLSX) { InputValueExtractor inputValueExtractor = new InputValueExtractor(); return new ExcelOpenXmlTemplate(stream, configuration, inputValueExtractor); } throw new NotSupportedException("Please Issue for me"); } } public enum ExcelType { XLSX, CSV, UNKNOWN } public interface IConfiguration { } public abstract class Configuration : IConfiguration { public CultureInfo Culture { get; set; } = CultureInfo.InvariantCulture; public DynamicExcelColumn[] DynamicColumns { get; set; } public int BufferSize { get; set; } = 524288; public bool FastMode { get; set; } public bool DynamicColumnFirst { get; set; } } internal interface IExcelReader : IDisposable { IEnumerable<IDictionary<string, object>> Query(bool UseHeaderRow, string sheetName, string startCell); IEnumerable<T> Query<T>(string sheetName, string startCell) where T : class, new(); Task<IEnumerable<IDictionary<string, object>>> QueryAsync(bool UseHeaderRow, string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)); Task<IEnumerable<T>> QueryAsync<T>(string sheetName, string startCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new(); IEnumerable<IDictionary<string, object>> QueryRange(bool UseHeaderRow, string sheetName, string startCell, string endCell); IEnumerable<T> QueryRange<T>(string sheetName, string startCell, string endCell) where T : class, new(); Task<IEnumerable<IDictionary<string, object>>> QueryAsyncRange(bool UseHeaderRow, string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default(CancellationToken)); Task<IEnumerable<T>> QueryAsyncRange<T>(string sheetName, string startCell, string endCell, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new(); } internal interface IExcelTemplate { void SaveAsByTemplate(string templatePath, object value); void SaveAsByTemplate(byte[] templateBtyes, object value); void MergeSameCells(string path); void MergeSameCells(byte[] fileInBytes); } internal interface IExcelTemplateAsync : IExcelTemplate { Task SaveAsByTemplateAsync(string templatePath, object value, CancellationToken cancellationToken = default(CancellationToken)); Task SaveAsByTemplateAsync(byte[] templateBtyes, object value, CancellationToken cancellationToken = default(CancellationToken)); Task MergeSameCellsAsync(string path, CancellationToken cancellationToken = default(CancellationToken)); Task MergeSameCellsAsync(byte[] fileInBytes, CancellationToken cancellationToken = default(CancellationToken)); } internal interface IExcelWriter { int[] SaveAs(); Task<int[]> SaveAsAsync(CancellationToken cancellationToken = default(CancellationToken)); int Insert(bool overwriteSheet = false); Task<int> InsertAsync(bool overwriteSheet = false, CancellationToken cancellationToken = default(CancellationToken)); } public interface IMiniExcelDataReader : IDataReader, IDataRecord, IDisposable { Task CloseAsync(); Task<string> GetNameAsync(int i, CancellationToken cancellationToken = default(CancellationToken)); Task<object> GetValueAsync(int i, CancellationToken cancellationToken = default(CancellationToken)); Task<bool> NextResultAsync(CancellationToken cancellationToken = default(CancellationToken)); Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken)); } public static class MiniExcel { public static string LISENCE_CODE; public static async Task<int> InsertAsync(string path, object value, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, bool printHeader = true, bool overwriteSheet = false, CancellationToken cancellationToken = default(CancellationToken)) { if (Path.GetExtension(path).ToLowerInvariant() == ".xlsm") { throw new NotSupportedException("MiniExcel's Insert does not support the .xlsm format"); } if (!File.Exists(path)) { return (await SaveAsAsync(path, value, printHeader, sheetName, excelType, configuration, overwriteFile: false, cancellationToken)).FirstOrDefault(); } if (excelType == ExcelType.CSV) { using (FileStream stream2 = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read, 4096, FileOptions.SequentialScan)) { return await stream2.InsertAsync(value, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration, printHeader, overwriteSheet, cancellationToken); } } using FileStream stream2 = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.SequentialScan); return await stream2.InsertAsync(value, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration, printHeader, overwriteSheet, cancellationToken); } public static async Task<int> InsertAsync(this Stream stream, object value, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, bool printHeader = true, bool overwriteSheet = false, CancellationToken cancellationToken = default(CancellationToken)) { stream.Seek(0L, SeekOrigin.End); if (excelType == ExcelType.CSV) { object value2 = ((value is IEnumerable || value is IDataReader) ? value : new object[1] { value }.AsEnumerable()); return await ExcelWriterFactory.GetProvider(stream, value2, sheetName, excelType, configuration, printHeader: false).InsertAsync(overwriteSheet, cancellationToken); } IConfiguration configuration2 = configuration ?? new OpenXmlConfiguration { FastMode = true }; return await ExcelWriterFactory.GetProvider(stream, value, sheetName, excelType, configuration2, printHeader).InsertAsync(overwriteSheet, cancellationToken); } public static async Task<int[]> SaveAsAsync(string path, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, bool overwriteFile = false, CancellationToken cancellationToken = default(CancellationToken)) { if (Path.GetExtension(path).ToLowerInvariant() == ".xlsm") { throw new NotSupportedException("MiniExcel's SaveAs does not support the .xlsm format"); } using FileStream stream = (overwriteFile ? File.Create(path) : new FileStream(path, FileMode.CreateNew)); return await stream.SaveAsAsync(value, printHeader, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration, cancellationToken); } public static async Task<int[]> SaveAsAsync(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { return await ExcelWriterFactory.GetProvider(stream, value, sheetName, excelType, configuration, printHeader).SaveAsAsync(cancellationToken); } public static async Task MergeSameCellsAsync(string mergedFilePath, string path, ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { await Task.Run(delegate { MergeSameCells(mergedFilePath, path, excelType, configuration); }, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public static async Task MergeSameCellsAsync(this Stream stream, string path, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { await ExcelTemplateFactory.GetProvider(stream, configuration, excelType).MergeSameCellsAsync(path, cancellationToken); } public static async Task MergeSameCellsAsync(this Stream stream, byte[] fileBytes, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { await ExcelTemplateFactory.GetProvider(stream, configuration, excelType).MergeSameCellsAsync(fileBytes, cancellationToken); } public static async Task<IEnumerable<dynamic>> QueryAsync(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { return await Task.Run(() => Query(path, useHeaderRow, sheetName, excelType, startCell, configuration), cancellationToken); } public static async Task<IEnumerable<T>> QueryAsync<T>(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() { return await ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration).QueryAsync<T>(sheetName, startCell, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public static async Task<IEnumerable<T>> QueryAsync<T>(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class, new() { return await Task.Run(() => Query<T>(path, sheetName, excelType, startCell, configuration), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public static async Task<IEnumerable<dynamic>> QueryAsync(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { TaskCompletionSource<IEnumerable<dynamic>> tcs = new TaskCompletionSource<IEnumerable<object>>(); cancellationToken.Register(delegate { tcs.TrySetCanceled(); }); await Task.Run(delegate { try { tcs.TrySetResult(stream.Query(useHeaderRow, sheetName, excelType, startCell, configuration)); } catch (Exception exception) { tcs.TrySetException(exception); } }, cancellationToken); return await tcs.Task; } public static async Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templatePath, value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public static async Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { await ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplateAsync(templateBytes, value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public static async Task SaveAsByTemplateAsync(string path, string templatePath, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { await Task.Run(delegate { SaveAsByTemplate(path, templatePath, value, configuration); }, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public static async Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value, IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { await Task.Run(delegate { SaveAsByTemplate(path, templateBytes, value, configuration); }, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } [Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")] public static async Task<DataTable> QueryAsDataTableAsync(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { return await Task.Run(() => QueryAsDataTable(path, useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } [Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")] public static async Task<DataTable> QueryAsDataTableAsync(this Stream stream, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null, CancellationToken cancellationToken = default(CancellationToken)) { return await Task.Run(() => stream.QueryAsDataTable(useHeaderRow, sheetName, excelType, startCell, configuration), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public static MiniExcelDataReader GetReader(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) { return new MiniExcelDataReader(FileHelper.OpenSharedRead(path), useHeaderRow, sheetName, excelType, startCell, configuration); } public static MiniExcelDataReader GetReader(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) { return new MiniExcelDataReader(stream, useHeaderRow, sheetName, excelType, startCell, configuration); } public static int Insert(string path, object value, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, bool printHeader = true, bool overwriteSheet = false) { if (Path.GetExtension(path).ToLowerInvariant() == ".xlsm") { throw new NotSupportedException("MiniExcel's Insert does not support the .xlsm format"); } if (!File.Exists(path)) { return SaveAs(path, value, printHeader, sheetName, excelType, configuration).FirstOrDefault(); } if (excelType == ExcelType.CSV) { using (FileStream stream = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read, 4096, FileOptions.SequentialScan)) { return stream.Insert(value, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration, printHeader, overwriteSheet); } } using FileStream stream2 = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 4096, FileOptions.SequentialScan); return stream2.Insert(value, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration, printHeader, overwriteSheet); } public static int Insert(this Stream stream, object value, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null, bool printHeader = true, bool overwriteSheet = false) { stream.Seek(0L, SeekOrigin.End); if (excelType == ExcelType.CSV) { object value2 = ((value is IEnumerable || value is IDataReader) ? value : new object[1] { value }.AsEnumerable()); return ExcelWriterFactory.GetProvider(stream, value2, sheetName, excelType, configuration, printHeader: false).Insert(overwriteSheet); } IConfiguration configuration2 = configuration ?? new OpenXmlConfiguration { FastMode = true }; return ExcelWriterFactory.GetProvider(stream, value, sheetName, excelType, configuration2, printHeader).Insert(overwriteSheet); } public static int[] SaveAs(string path, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.UNKNOWN, IConfiguration configuration = null, bool overwriteFile = false) { if (Path.GetExtension(path).ToLowerInvariant() == ".xlsm") { throw new NotSupportedException("MiniExcel's SaveAs does not support the .xlsm format"); } using FileStream stream = (overwriteFile ? File.Create(path) : new FileStream(path, FileMode.CreateNew)); return stream.SaveAs(value, printHeader, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), configuration); } public static int[] SaveAs(this Stream stream, object value, bool printHeader = true, string sheetName = "Sheet1", ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null) { return ExcelWriterFactory.GetProvider(stream, value, sheetName, excelType, configuration, printHeader).SaveAs(); } public static IEnumerable<T> Query<T>(string path, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) where T : class, new() { using FileStream stream = FileHelper.OpenSharedRead(path); foreach (T item in stream.Query<T>(sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration)) { yield return item; } } public static IEnumerable<T> Query<T>(this Stream stream, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) where T : class, new() { using IExcelReader excelReader = ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration); foreach (T item in excelReader.Query<T>(sheetName, startCell)) { yield return item; } } public static IEnumerable<dynamic> Query(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) { using FileStream stream = FileHelper.OpenSharedRead(path); foreach (object item in stream.Query(useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration)) { yield return item; } } public static IEnumerable<dynamic> Query(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) { using IExcelReader excelReader = ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration); foreach (IDictionary<string, object> item in excelReader.Query(useHeaderRow, sheetName, startCell)) { yield return item.Aggregate(new ExpandoObject(), delegate(IDictionary<string, object> dict, KeyValuePair<string, object> p) { dict.Add(p); return dict; }); } } public static IEnumerable<dynamic> QueryRange(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "a1", string endCell = "", IConfiguration configuration = null) { using FileStream stream = FileHelper.OpenSharedRead(path); foreach (object item in stream.QueryRange(useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), (startCell == "") ? "a1" : startCell, endCell, configuration)) { yield return item; } } public static IEnumerable<dynamic> QueryRange(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "a1", string endCell = "", IConfiguration configuration = null) { using IExcelReader excelReader = ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration); foreach (IDictionary<string, object> item in excelReader.QueryRange(useHeaderRow, sheetName, (startCell == "") ? "a1" : startCell, endCell)) { yield return item.Aggregate(new ExpandoObject(), delegate(IDictionary<string, object> dict, KeyValuePair<string, object> p) { dict.Add(p); return dict; }); } } public static void SaveAsByTemplate(string path, string templatePath, object value, IConfiguration configuration = null) { using FileStream stream = File.Create(path); stream.SaveAsByTemplate(templatePath, value, configuration); } public static void SaveAsByTemplate(string path, byte[] templateBytes, object value, IConfiguration configuration = null) { using FileStream stream = File.Create(path); stream.SaveAsByTemplate(templateBytes, value, configuration); } public static void SaveAsByTemplate(this Stream stream, string templatePath, object value, IConfiguration configuration = null) { ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplate(templatePath, value); } public static void SaveAsByTemplate(this Stream stream, byte[] templateBytes, object value, IConfiguration configuration = null) { ExcelTemplateFactory.GetProvider(stream, configuration).SaveAsByTemplate(templateBytes, value); } public static void MergeSameCells(string mergedFilePath, string path, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null) { using FileStream stream = File.Create(mergedFilePath); stream.MergeSameCells(path, excelType, configuration); } public static void MergeSameCells(this Stream stream, string path, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null) { ExcelTemplateFactory.GetProvider(stream, configuration, excelType).MergeSameCells(path); } public static void MergeSameCells(this Stream stream, byte[] filePath, ExcelType excelType = ExcelType.XLSX, IConfiguration configuration = null) { ExcelTemplateFactory.GetProvider(stream, configuration, excelType).MergeSameCells(filePath); } [Obsolete("QueryAsDataTable is not recommended, because it'll load all data into memory.")] public static DataTable QueryAsDataTable(string path, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) { using FileStream stream = FileHelper.OpenSharedRead(path); return stream.QueryAsDataTable(useHeaderRow, sheetName, ExcelTypeHelper.GetExcelType(path, excelType), startCell, configuration); } public static DataTable QueryAsDataTable(this Stream stream, bool useHeaderRow = true, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) { if (sheetName == null && excelType != ExcelType.CSV) { sheetName = stream.GetSheetNames(configuration as OpenXmlConfiguration).First(); } DataTable dataTable = new DataTable(sheetName); bool flag = true; IEnumerable<IDictionary<string, object>> enumerable = ExcelReaderFactory.GetProvider(stream, ExcelTypeHelper.GetExcelType(stream, excelType), configuration).Query(UseHeaderRow: false, sheetName, startCell); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (IDictionary<string, object> item in enumerable) { if (flag) { foreach (KeyValuePair<string, object> item2 in item) { string text = ((!useHeaderRow) ? item2.Key : item2.Value?.ToString()); if (!string.IsNullOrWhiteSpace(text)) { DataColumn column = new DataColumn(text, typeof(object)) { Caption = text }; dataTable.Columns.Add(column); dictionary.Add(item2.Key, text); } } dataTable.BeginLoadData(); flag = false; if (useHeaderRow) { continue; } } DataRow dataRow = dataTable.NewRow(); foreach (KeyValuePair<string, string> item3 in dictionary) { dataRow[item3.Value] = item[item3.Key]; } dataTable.Rows.Add(dataRow); } dataTable.EndLoadData(); return dataTable; } public static List<string> GetSheetNames(string path, OpenXmlConfiguration config = null) { using FileStream stream = FileHelper.OpenSharedRead(path); return stream.GetSheetNames(config); } public static List<string> GetSheetNames(this Stream stream, OpenXmlConfiguration config = null) { config = config ?? OpenXmlConfiguration.DefaultConfig; ExcelOpenXmlZip excelOpenXmlZip = new ExcelOpenXmlZip(stream); return (from s in new ExcelOpenXmlSheetReader(stream, config).GetWorkbookRels(excelOpenXmlZip.entries) select s.Name).ToList(); } public static List<SheetInfo> GetSheetInformations(string path, OpenXmlConfiguration config = null) { using FileStream stream = FileHelper.OpenSharedRead(path); return stream.GetSheetInformations(config); } public static List<SheetInfo> GetSheetInformations(this Stream stream, OpenXmlConfiguration config = null) { config = config ?? OpenXmlConfiguration.DefaultConfig; ExcelOpenXmlZip excelOpenXmlZip = new ExcelOpenXmlZip(stream); return new ExcelOpenXmlSheetReader(stream, config).GetWorkbookRels(excelOpenXmlZip.entries).Select((SheetRecord s, int i) => s.ToSheetInfo((uint)i)).ToList(); } public static ICollection<string> GetColumns(string path, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) { using FileStream stream = FileHelper.OpenSharedRead(path); return stream.GetColumns(useHeaderRow, sheetName, excelType, startCell, configuration); } public static ICollection<string> GetColumns(this Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) { return (stream.Query(useHeaderRow, sheetName, excelType, startCell, configuration).FirstOrDefault() as IDictionary<string, object>)?.Keys; } public static void ConvertCsvToXlsx(string csv, string xlsx) { using FileStream csv2 = FileHelper.OpenSharedRead(csv); using FileStream xlsx2 = new FileStream(xlsx, FileMode.CreateNew); ConvertCsvToXlsx(csv2, xlsx2); } public static void ConvertCsvToXlsx(Stream csv, Stream xlsx) { IEnumerable<object> value = csv.Query(useHeaderRow: false, null, ExcelType.CSV); xlsx.SaveAs(value, printHeader: false); } public static void ConvertXlsxToCsv(string xlsx, string csv) { using FileStream xlsx2 = FileHelper.OpenSharedRead(xlsx); using FileStream csv2 = new FileStream(csv, FileMode.CreateNew); ConvertXlsxToCsv(xlsx2, csv2); } public static void ConvertXlsxToCsv(Stream xlsx, Stream csv) { IEnumerable<object> value = xlsx.Query(useHeaderRow: false, null, ExcelType.XLSX); csv.SaveAs(value, printHeader: false, "Sheet1", ExcelType.CSV); } } public class MiniExcelDataReader : MiniExcelDataReaderBase { private readonly IEnumerator<IDictionary<string, object>> _source; private readonly int _fieldCount; private readonly List<string> _keys; private readonly Stream _stream; private bool _isFirst = true; private bool _disposed; public override int FieldCount => _fieldCount; internal MiniExcelDataReader(Stream stream, bool useHeaderRow = false, string sheetName = null, ExcelType excelType = ExcelType.UNKNOWN, string startCell = "A1", IConfiguration configuration = null) { _stream = stream ?? throw new ArgumentNullException("stream"); _source = _stream.Query(useHeaderRow, sheetName, excelType, startCell, configuration).Cast<IDictionary<string, object>>().GetEnumerator(); if (_source.MoveNext()) { _keys = _source.Current?.Keys.ToList() ?? new List<string>(); _fieldCount = _keys.Count; } } public override object GetValue(int i) { if (_source.Current == null) { throw new InvalidOperationException("No current row available."); } return _source.Current[_keys[i]]; } public override bool Read() { if (_isFirst) { _isFirst = false; return true; } return _source.MoveNext(); } public override string GetName(int i) { return _keys[i]; } public override int GetOrdinal(string name) { return _keys.IndexOf(name); } protected override void Dispose(bool disposing) { if (!_disposed) { if (disposing) { _stream?.Dispose(); _source?.Dispose(); } _disposed = true; } base.Dispose(disposing); } public new void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } public abstract class MiniExcelDataReaderBase : IMiniExcelDataReader, IDataReader, IDataRecord, IDisposable { public virtual object this[int i] => null; public virtual object this[string name] => null; public virtual int Depth { get; } public virtual bool IsClosed { get; } public virtual int RecordsAffected { get; } public virtual int FieldCount { get; } public virtual bool GetBoolean(int i) { return false; } public virtual byte GetByte(int i) { return 0; } public virtual long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferOffset, int length) { return 0L; } public virtual char GetChar(int i) { return '\0'; } public virtual long GetChars(int i, long fieldOffset, char[] buffer, int bufferOffset, int length) { return 0L; } public virtual IDataReader GetData(int i) { return null; } public virtual string GetDataTypeName(int i) { return string.Empty; } public virtual DateTime GetDateTime(int i) { return DateTime.MinValue; } public virtual decimal GetDecimal(int i) { return 0m; } public virtual double GetDouble(int i) { return 0.0; } public virtual Type GetFieldType(int i) { return null; } public virtual float GetFloat(int i) { return 0f; } public virtual Guid GetGuid(int i) { return Guid.Empty; } public virtual short GetInt16(int i) { return 0; } public virtual int GetInt32(int i) { return 0; } public virtual long GetInt64(int i) { return 0L; } public virtual int GetOrdinal(string name) { return 0; } public virtual DataTable GetSchemaTable() { return null; } public virtual string GetString(int i) { return string.Empty; } public virtual int GetValues(object[] values) { return 0; } public virtual bool IsDBNull(int i) { return false; } public virtual bool NextResult() { return false; } public virtual Task<bool> NextResultAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return MiniExcelTask.FromCanceled<bool>(cancellationToken); } try { return NextResult() ? Task.FromResult(result: true) : Task.FromResult(result: false); } catch (Exception exception) { return MiniExcelTask.FromException<bool>(exception); } } public abstract string GetName(int i); public virtual Task<string> GetNameAsync(int i, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return MiniExcelTask.FromCanceled<string>(cancellationToken); } try { return Task.FromResult(GetName(i)); } catch (Exception exception) { return MiniExcelTask.FromException<string>(exception); } } public abstract object GetValue(int i); public virtual Task<object> GetValueAsync(int i, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return MiniExcelTask.FromCanceled<object>(cancellationToken); } try { return Task.FromResult(GetValue(i)); } catch (Exception exception) { return MiniExcelTask.FromException<object>(exception); } } public abstract bool Read(); public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return MiniExcelTask.FromCanceled<bool>(cancellationToken); } try { return Read() ? Task.FromResult(result: true) : Task.FromResult(result: false); } catch (Exception exception) { return MiniExcelTask.FromException<bool>(exception); } } public virtual void Close() { } public virtual Task CloseAsync() { try { Close(); return MiniExcelTask.CompletedTask; } catch (Exception exception) { return MiniExcelTask.FromException(exception); } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { Close(); } } } internal class MiniExcelTask { public static Task CompletedTask = Task.CompletedTask; public static Task FromException(Exception exception) { return Task.FromException(exception); } public static Task<T> FromException<T>(Exception exception) { return Task.FromException<T>(exception); } public static Task FromCanceled(CancellationToken cancellationToken) { return Task.FromCanceled(cancellationToken); } public static Task<T> FromCanceled<T>(CancellationToken cancellationToken) { return Task.FromCanceled<T>(cancellationToken); } } public class MemberGetter { private readonly Func<object, object> m_getFunc; public MemberGetter(PropertyInfo property) { m_getFunc = CreateGetterDelegate(property); } public MemberGetter(FieldInfo fieldInfo) { m_getFunc = CreateGetterDelegate(fieldInfo); } public object Invoke(object instance) { return m_getFunc(instance); } private static Func<object, object> CreateGetterDelegate(PropertyInfo property) { ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); return Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Property(Expression.Convert(parameterExpression, property.DeclaringType), property), typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile(); } private static Func<object, object> CreateGetterDelegate(FieldInfo fieldInfo) { ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); return Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Field(Expression.Convert(parameterExpression, fieldInfo.DeclaringType), fieldInfo), typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile(); } } public class MemberSetter { private readonly Action<object, object> setFunc; public MemberSetter(PropertyInfo property) { if (property == null) { throw new ArgumentNullException("property"); } setFunc = CreateSetterDelegate(property); } public void Invoke(object instance, object value) { setFunc(instance, value); } private static Action<object, object> CreateSetterDelegate(PropertyInfo property) { ParameterExpression parameterExpression = Expression.Parameter(typeof(object)); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object)); UnaryExpression instance = Expression.Convert(parameterExpression, property.DeclaringType); UnaryExpression unaryExpression = Expression.Convert(parameterExpression2, property.PropertyType); return Expression.Lambda<Action<object, object>>(Expression.Call(instance, property.GetSetMethod(nonPublic: true), unaryExpression), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); } } public abstract class Member { } public class Property : Member { private static readonly ConcurrentDictionary<Type, Property[]> m_cached = new ConcurrentDictionary<Type, Property[]>(); private readonly MemberGetter m_geter; private readonly MemberSetter m_seter; public bool CanRead { get; private set; } public bool CanWrite { get; private set; } public PropertyInfo Info { get; private set; } public string Name { get; protected set; } public Property(PropertyInfo property) { Name = property.Name; Info = property; if (property.CanRead) { CanRead = true; m_geter = new MemberGetter(property); } if (property.CanWrite) { CanWrite = true; m_seter = new MemberSetter(property); } } public static Property[] GetProperties(Type type) { return m_cached.GetOrAdd(type, (Type t) => (from p in t.GetProperties() select new Property(p)).ToArray()); } public object GetValue(object instance) { if (m_geter == null) { throw new NotSupportedException(); } return m_geter.Invoke(instance); } public void SetValue(object instance, object value) { if (m_seter == null) { throw new NotSupportedException(Name + " can't set value"); } m_seter.Invoke(instance, value); } } } namespace MiniExcelLibs.Zip { internal class ExcelOpenXmlZip : IDisposable { private readonly Dictionary<string, ZipArchiveEntry> _entries; private bool _disposed; internal MiniExcelZipArchive zipFile; public ReadOnlyCollection<ZipArchiveEntry> entries; private static readonly XmlReaderSettings XmlSettings = new XmlReaderSettings { IgnoreComments = true, IgnoreWhitespace = true, XmlResolver = null }; public ExcelOpenXmlZip(Stream fileStream, ZipArchiveMode mode = ZipArchiveMode.Read, bool leaveOpen = false, Encoding entryNameEncoding = null) { zipFile = new MiniExcelZipArchive(fileStream, mode, leaveOpen, entryNameEncoding); _entries = new Dictionary<string, ZipArchiveEntry>(StringComparer.OrdinalIgnoreCase); try { entries = zipFile.Entries; } catch (InvalidDataException ex) { throw new InvalidDataException("It's not legal excel zip, please check or issue for me. " + ex.Message); } foreach (ZipArchiveEntry entry in zipFile.Entries) { _entries.Add(entry.FullName.Replace('\\', '/'), entry); } } public ZipArchiveEntry GetEntry(string path) { if (_entries.TryGetValue(path, out var value)) { return value; } return null; } public XmlReader GetXmlReader(string path) { ZipArchiveEntry entry = GetEntry(path); if (entry != null) { return XmlReader.Create(entry.Open(), XmlSettings); } return null; } ~ExcelOpenXmlZip() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (!_disposed) { if (disposing && zipFile != null) { zipFile.Dispose(); zipFile = null; } _disposed = true; } } } public class MiniExcelZipArchive : ZipArchive { public MiniExcelZipArchive(Stream stream, ZipArchiveMode mode, bool leaveOpen, Encoding entryNameEncoding) : base(stream, mode, leaveOpen, entryNameEncoding) { } public new void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } } internal class ZipPackageInfo { public ZipArchiveEntry ZipArchiveEntry { get; set; } public string ContentType { get; set; } public ZipPackageInfo(ZipArchiveEntry zipArchiveEntry, string contentType) { ZipArchiveEntry = zipArchiveEntry; ContentType = contentType; } } } namespace MiniExcelLibs.WriteAdapter { internal class AsyncEnumerableWriteAdapter<T> : IAsyncMiniExcelWriteAdapter { private readonly IAsyncEnumerable<T> _values; private readonly Configuration _configuration; private IAsyncEnumerator<T> _enumerator; private bool _empty; public AsyncEnumerableWriteAdapter(IAsyncEnumerable<T> values, Configuration configuration) { _values = values; _configuration = configuration; } public async Task<List<ExcelColumnInfo>> GetColumnsAsync() { if (CustomPropertyHelper.TryGetTypeColumnInfo(typeof(T), _configuration, out var props)) { return props; } _enumerator = _values.GetAsyncEnumerator(); if (!(await _enumerator.MoveNextAsync())) { _empty = true; return null; } return CustomPropertyHelper.GetColumnInfoFromValue(_enumerator.Current, _configuration); } public async IAsyncEnumerable<IAsyncEnumerable<CellWriteInfo>> GetRowsAsync(List<ExcelColumnInfo> props, [EnumeratorCancellation] CancellationToken cancellationToken) { if (_empty) { yield break; } if (_enumerator == null) { _enumerator = _values.GetAsyncEnumerator(); if (!(await _enumerator.MoveNextAsync())) { yield break; } } do { cancellationToken.ThrowIfCancellationRequested(); yield return GetRowValuesAsync(_enumerator.Current, props); } while (await _enumerator.MoveNextAsync()); } public static async IAsyncEnumerable<CellWriteInfo> GetRowValuesAsync(T currentValue, List<ExcelColumnInfo> props) { int column = 1; foreach (ExcelColumnInfo prop in props) { if (prop == null) { column++; continue; } if ((object)currentValue is IDictionary<string, object> dictionary) { yield return new CellWriteInfo(dictionary[prop.Key.ToString()], column, prop); } else if ((object)currentValue is IDictionary dictionary2) { yield return new CellWriteInfo(dictionary2[prop.Key], column, prop); } else { yield return new CellWriteInfo(prop.Property.GetValue(currentValue), column, prop); } column++; } } } internal class DataReaderWriteAdapter : IMiniExcelWriteAdapter { private readonly IDataReader _reader; private readonly Configuration _configuration; public DataReaderWriteAdapter(IDataReader reader, Configuration configuration) { _reader = reader; _configuration = configuration; } public bool TryGetKnownCount(out int count) { count = 0; return false; } public List<ExcelColumnInfo> GetColumns() { List<ExcelColumnInfo> list = new List<ExcelColumnInfo>(); for (int i = 0; i < _reader.FieldCount; i++) { string columnName = _reader.GetName(i); if (!_configuration.DynamicColumnFirst) { ExcelColumnInfo columnInfosFromDynamicConfiguration = CustomPropertyHelper.GetColumnInfosFromDynamicConfiguration(columnName, _configuration); list.Add(columnInfosFromDynamicConfiguration); } else if (_configuration.DynamicColumns.Any((DynamicExcelColumn a) => string.Equals(a.Key, columnName, StringComparison.OrdinalIgnoreCase))) { ExcelColumnInfo columnInfosFromDynamicConfiguration2 = CustomPropertyHelper.GetColumnInfosFromDynamicConfiguration(columnName, _configuration); list.Add(columnInfosFromDynamicConfiguration2); } } return list; } public IEnumerable<IEnumerable<CellWriteInfo>> GetRows(List<ExcelColumnInfo> props, CancellationToken cancellationToken = default(CancellationToken)) { while (_reader.Read()) { cancellationToken.ThrowIfCancellationRequested(); yield return GetRowValues(props); } } private IEnumerable<CellWriteInfo> GetRowValues(List<ExcelColumnInfo> props) { int i = 0; int column = 1; while (i < _reader.FieldCount) { if (_configuration.DynamicColumnFirst) { int ordinal = _reader.GetOrdinal(props[i].Key.ToString()); yield return new CellWriteInfo(_reader.GetValue(ordinal), column, props[i]); } else { yield return new CellWriteInfo(_reader.GetValue(i), column, props[i]); } i++; column++; } } } internal class DataTableWriteAdapter : IMiniExcelWriteAdapter { private readonly DataTable _dataTable; private readonly Configuration _configuration; public DataTableWriteAdapter(DataTable dataTable, Configuration configuration) { _dataTable = dataTable; _configuration = configuration; } public bool TryGetKnownCount(out int count) { count = _dataTable.Rows.Count; return true; } public List<ExcelColumnInfo> GetColumns() { List<ExcelColumnInfo> list = new List<ExcelColumnInfo>(); for (int i = 0; i < _dataTable.Columns.Count; i++) { ExcelColumnInfo columnInfosFromDynamicConfiguration = CustomPropertyHelper.GetColumnInfosFromDynamicConfiguration(_dataTable.Columns[i].Caption ?? _dataTable.Columns[i].ColumnName, _configuration); list.Add(columnInfosFromDynamicConfiguration); } return list; } public IEnumerable<IEnumerable<CellWriteInfo>> GetRows(List<ExcelColumnInfo> props, CancellationToken cancellationToken = default(CancellationToken)) { for (int row = 0; row < _dataTable.Rows.Count; row++) { cancellationToken.ThrowIfCancellationRequested(); yield return GetRowValues(row, props); } } private IEnumerable<CellWriteInfo> GetRowValues(int row, List<ExcelColumnInfo> props) { int i = 0; int column = 1; while (i < _dataTable.Columns.Count) { yield return new CellWriteInfo(_dataTable.Rows[row][i], column, props[i]); i++; column++; } } } internal class EnumerableWriteAdapter : IMiniExcelWriteAdapter { private readonly IEnumerable _values; private readonly Configuration _configuration; private readonly Type _genericType; private IEnumerator _enumerator; private bool _empty; public EnumerableWriteAdapter(IEnumerable values, Configuration configuration) { _values = values; _configuration = configuration; _genericType = TypeHelper.GetGenericIEnumerables(values).FirstOrDefault(); } public bool TryGetKnownCount(out int count) { count = 0; if (_values is ICollection collection) { count = collection.Count; return true; } return false; } public List<ExcelColumnInfo> GetColumns() { if (CustomPropertyHelper.TryGetTypeColumnInfo(_genericType, _configuration, out var props)) { return props; } _enumerator = _values.GetEnumerator(); if (!_enumerator.MoveNext()) { try { _empty = true; return null; } finally { (_enumerator as IDisposable)?.Dispose(); _enumerator = null; } } return CustomPropertyHelper.GetColumnInfoFromValue(_enumerator.Current, _configuration); } public IEnumerable<IEnumerable<CellWriteInfo>> GetRows(List<ExcelColumnInfo> props, CancellationToken cancellationToken = default(CancellationToken)) { if (_empty) { yield break; } try { if (_enumerator == null) { _enumerator = _values.GetEnumerator(); if (!_enumerator.MoveNext()) { yield break; } } do { cancellationToken.ThrowIfCancellationRequested(); yield return GetRowValues(_enumerator.Current, props); } while (_enumerator.MoveNext()); } finally { EnumerableWriteAdapter enumerableWriteAdapter = this; (enumerableWriteAdapter._enumerator as IDisposable)?.Dispose(); enumerableWriteAdapter._enumerator = null; } } public static IEnumerable<CellWriteInfo> GetRowValues(object currentValue, List<ExcelColumnInfo> props) { int column = 1; foreach (ExcelColumnInfo prop in props) { object value = ((prop == null) ? null : ((!(currentValue is IDictionary<string, object> dictionary)) ? ((!(currentValue is IDictionary dictionary2)) ? prop.Property.GetValue(currentValue) : dictionary2[prop.Key]) : dictionary[prop.Key.ToString()])); yield return new CellWriteInfo(value, column, prop); column++; } } } internal interface IAsyncMiniExcelWriteAdapter { Task<List<ExcelColumnInfo>> GetColumnsAsync(); IAsyncEnumerable<IAsyncEnumerable<CellWriteInfo>> GetRowsAsync(List<ExcelColumnInfo> props, CancellationToken cancellationToken); } internal interface IMiniExcelWriteAdapter { bool TryGetKnownCount(out int count); List<ExcelColumnInfo> GetColumns(); IEnumerable<IEnumerable<CellWriteInfo>> GetRows(List<ExcelColumnInfo> props, CancellationToken cancellationToken = default(CancellationToken)); } internal readonly struct CellWriteInfo { public object Value { get; } public int CellIndex { get; } public ExcelColumnInfo Prop { get; } public CellWriteInfo(object value, int cellIndex, ExcelColumnInfo prop) { Value = value; CellIndex = cellIndex; Prop = prop; } } internal class MiniExcelDataReaderWriteAdapter : IAsyncMiniExcelWriteAdapter { private readonly IMiniExcelDataReader _reader; private readonly Configuration _configuration; public MiniExcelDataReaderWriteAdapter(IMiniExcelDataReader reader, Configuration configuration) { _reader = reader; _configuration = configuration; } public async Task<List<ExcelColumnInfo>> GetColumnsAsync() { List<ExcelColumnInfo> props = new List<ExcelColumnInfo>(); for (int i = 0; i < _reader.FieldCount; i++) { string columnName = await _reader.GetNameAsync(i); if (!_configuration.DynamicColumnFirst) { ExcelColumnInfo columnInfosFromDynamicConfiguration = CustomPropertyHelper.GetColumnInfosFromDynamicConfiguration(columnName, _configuration); props.Add(columnInfosFromDynamicConfiguration); } else if (_configuration.DynamicColumns.Any((DynamicExcelColumn a) => string.Equals(a.Key, columnName, StringComparison.OrdinalIgnoreCase))) { ExcelColumnInfo columnInfosFromDynamicConfiguration2 = CustomPropertyHelper.GetColumnInfosFromDynamicConfiguration(columnName, _configuration); props.Add(columnInfosFromDynamicConfiguration2); } } return props; } public async IAsyncEnumerable<IAsyncEnumerable<CellWriteInfo>> GetRowsAsync(List<ExcelColumnInfo> props, [EnumeratorCancellation] CancellationToken cancellationToken) { while (await _reader.ReadAsync()) { cancellationToken.ThrowIfCancellationRequested(); yield return GetRowValuesAsync(props); } } private async IAsyncEnumerable<CellWriteInfo> GetRowValuesAsync(List<ExcelColumnInfo> props) { int i = 0; int column = 1; while (i < _reader.FieldCount) { if (_configuration.DynamicColumnFirst) { int ordinal = _reader.GetOrdinal(props[i].Key.ToString()); yield return new CellWriteInfo(await _reader.GetValueAsync(ordinal), column, props[i]); } else { yield return new CellWriteInfo(await _reader.GetValueAsync(i), column, props[i]); } i++; column++; } } } internal static class MiniExcelWriteAdapterFactory { public static bool TryGetAsyncWriteAdapter(object values, Configuration configuration, out IAsyncMiniExcelWriteAdapter writeAdapter) { writeAdapter = null; if (values.GetType().IsAsyncEnumerable(out var genericArgument)) { Type type = typeof(AsyncEnumerableWriteAdapter<>).MakeGenericType(genericArgument); writeAdapter = (IAsyncMiniExcelWriteAdapter)Activator.CreateInstance(type, values, configuration); return true; } if (values is IMiniExcelDataReader reader) { writeAdapter = new MiniExcelDataReaderWriteAdapter(reader, configuration); return true; } return false; } public static IMiniExcelWriteAdapter GetWriteAdapter(object values, Configuration configuration) { if (!(values is IDataReader reader)) { if (!(values is IEnumerable values2)) { if (values is DataTable dataTable) { return new DataTableWriteAdapter(dataTable, configuration); } throw new NotImplementedException(); } return new EnumerableWriteAdapter(values2, configuration); } return new DataReaderWriteAdapter(reader, configuration); } } } namespace MiniExcelLibs.Utils { internal static class AttributeExtension { internal static TValue GetAttributeValue<TAttribute, TValue>(this Type attrType, Func<TAttribute, TValue> selector) where TAttribute : Attribute { TAttribute attr = attrType.GetCustomAttributes(typeof(TAttribute), inherit: true).FirstOrDefault() as TAttribute; return GetValueOrDefault(selector, attr); } private static TValue GetValueOrDefault<TAttribute, TValue>(Func<TAttribute, TValue> selector, TAttribute attr) where TAttribute : Attribute { if (attr != null) { return selector(attr); } return default(TValue); } internal static TAttribute GetAttribute<TAttribute>(this PropertyInfo prop, bool isInherit = true) where TAttribute : Attribute { return prop.GetAttributeValue((TAttribute attr) => attr, isInherit); } internal static TValue GetAttributeValue<TAttribute, TValue>(this PropertyInfo prop, Func<TAttribute, TValue> selector, bool isInherit = true) where TAttribute : Attribute { TAttribute attr = Attribute.GetCustomAttribute(prop, typeof(TAttribute), isInherit) as TAttribute; return GetValueOrDefault(selector, attr); } internal static bool IsUseAttribute<TAttribute>(this PropertyInfo prop) { return Attribute.GetCustomAttribute(prop, typeof(TAttribute)) != null; } } internal static class CalcChainHelper { public static string GetCalcChainContent(List<string> cellRefs, int sheetIndex) { StringBuilder stringBuilder = new StringBuilder(); foreach (string cellRef in cellRefs) { stringBuilder.Append($"<c r=\"{cellRef}\" i=\"{sheetIndex}\"/>"); } return stringBuilder.ToString(); } public static void GenerateCalcChainSheet(Stream calcChainStream, string calcChainContent) { using StreamWriter streamWriter = new StreamWriter(calcChainStream, Encoding.UTF8); streamWriter.Write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><calcChain xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">" + calcChainContent + "</calcChain>"); } } internal static class ColumnHelper { private const int GENERAL_COLUMN_INDEX = 255; private const int MAX_COLUMN_INDEX = 16383; private static int _IntMappingAlphabetCount; private static readonly ConcurrentDictionary<int, string> _IntMappingAlphabet; private static readonly ConcurrentDictionary<string, int> _AlphabetMappingInt; static ColumnHelper() { _IntMappingAlphabetCount = 0; _IntMappingAlphabet = new ConcurrentDictionary<int, string>(); _AlphabetMappingInt = new ConcurrentDictionary<string, int>(); _IntMappingAlphabetCount = _IntMappingAlphabet.Count; CheckAndSetMaxColumnIndex(255); } public static string GetAlphabetColumnName(int columnIndex) { CheckAndSetMaxColumnIndex(columnIndex); if (_IntMappingAlphabet.TryGetValue(columnIndex, out var value)) { return value; } throw new KeyNotFoundException(); } public static int GetColumnIndex(string columnName) { if (_AlphabetMappingInt.TryGetValue(columnName, out var value)) { CheckAndSetMaxColumnIndex(value); } return value; } private static void CheckAndSetMaxColumnIndex(int columnIndex) { if (columnIndex < _IntMappingAlphabetCount) { return; } if (columnIndex > 16383) { throw new InvalidDataException($"ColumnIndex {columnIndex} over excel vaild max index."); } int i; for (i = _IntMappingAlphabet.Count; i <= columnIndex; i++) { _IntMappingAlphabet.AddOrUpdate(i, IntToLetters(i), (int a, string b) => IntToLetters(i)); _AlphabetMappingInt.AddOrUpdate(IntToLetters(i), i, (string a, int b) => i); } _IntMappingAlphabetCount = _IntMappingAlphabet.Count; } internal static string IntToLetters(int value) { value++; string text = string.Empty; while (--value >= 0) { text = (char)(65 + value % 26) + text; value /= 26; } return text; } } internal class ExcelColumnInfo { public object Key { get; set; } public int? ExcelColumnIndex { get; set; } public string ExcelColumnName { get; set; } public string[] ExcelColumnAliases { get; set; } public Property Property { get; set; } public Type ExcludeNullableType { get; set; } public bool Nullable { get; internal set; } public string ExcelFormat { get; internal set; } public double? ExcelColumnWidth { get; internal set; } public string ExcelIndexName { get; internal set; } public bool ExcelIgnore { get; internal set; } public int ExcelFormatId { get; internal set; } public ColumnType ExcelColumnType { get; internal set; } public Func<object, object> CustomFormatter { get; set; } } internal class ExcellSheetInfo { public object Key { get; set; } public string ExcelSheetName { get; set; } public SheetState ExcelSheetState { get; set; } private string ExcelSheetStateAsString => ExcelSheetState.ToString().ToLower(); public SheetDto ToDto(int sheetIndex) { return new SheetDto { Name = ExcelSheetName, SheetIdx = sheetIndex, State = ExcelSheetStateAsString }; } } internal static class CustomPropertyHelper { internal static IDictionary<string, object> GetEmptyExpandoObject(int maxColumnIndex, int startCellIndex) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); for (int i = startCellIndex; i <= maxColumnIndex; i++) { string alphabetColumnName = ColumnHelper.GetAlphabetColumnName(i); if (!dictionary.ContainsKey(alphabetColumnName)) { dictionary.Add(alphabetColumnName, null); } } return dictionary; } internal static IDictionary<string, object> GetEmptyExpandoObject(Dictionary<int, string> hearrows) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); foreach (KeyValuePair<int, string> hearrow in hearrows) { if (!dictionary.ContainsKey(hearrow.Value)) { dictionary.Add(hearrow.Value, null); } } return dictionary; } internal static List<ExcelColumnInfo> GetSaveAsProperties(this Type type, Configuration configuration) { List<ExcelColumnInfo> list = (from prop in GetExcelPropertyInfo(type, BindingFlags.Instance | BindingFlags.Public, configuration) where prop.Property.CanRead select prop).ToList(); if (list.Count == 0) { throw new InvalidOperationException(type.Name + " un-ignore properties count can't be 0"); } return SortCustomProps(list); } internal static List<ExcelColumnInfo> SortCustomProps(List<ExcelColumnInfo> props) { List<ExcelColumnInfo> list = props.Where((ExcelColumnInfo w) => w.ExcelColumnIndex.HasValue && w.ExcelColumnIndex > -1).ToList(); if ((from g in list group g by g.ExcelColumnIndex).Any((IGrouping<int?, ExcelColumnInfo> _) => _.Count() > 1)) { throw new InvalidOperationException("Duplicate column name"); } int num = props.Count - 1; if (list.Count != 0) { num = Math.Max(list.Max((ExcelColumnInfo w) => w.ExcelColumnIndex).Value, num); } List<ExcelColumnInfo> source = props.Where((ExcelColumnInfo w) => !w.ExcelColumnIndex.HasValue || w.ExcelColumnIndex.GetValueOrDefault() == -1).ToList(); List<ExcelColumnInfo> list2 = new List<ExcelColumnInfo>(); int num2 = 0; int i; for (i = 0; i <= num; i++) { ExcelColumnInfo excelColumnInfo = list.SingleOrDefault((ExcelColumnInfo s) => s.ExcelColumnIndex == i); if (excelColumnInfo != null) { list2.Add(excelColumnInfo); continue; } ExcelColumnInfo excelColumnInfo2 = source.ElementAtOrDefault(num2); if (excelColumnInfo2 == null) { list2.Add(null); } else { excelColumnInfo2.ExcelColumnIndex = i; list2.Add(excelColumnInfo2); } num2++; } return list2; } internal static List<ExcelColumnInfo> GetExcelCustomPropertyInfos(Type type, string[] keys, Configuration configuration) { List<ExcelColumnInfo> list = (from prop in GetExcelPropertyInfo(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, configuration) where prop.Property.Info.GetSetMethod() != null && !prop.Property.Info.GetAttributeValue((ExcelIgnoreAttribute x) => x.ExcelIgnore) && !prop.Property.Info.GetAttributeValue((ExcelColumnAttribute x) => x.Ignore) select prop).ToList(); if (list.Count == 0) { throw new InvalidOperationException(type.Name + " un-ignore properties count can't be 0"); } if ((from w in list where w.ExcelColumnIndex.HasValue && w.ExcelColumnIndex > -1 select w into g group g by g.ExcelColumnIndex).Any((IGrouping<int?, ExcelColumnInfo> _) => _.Count() > 1)) { throw new InvalidOperationException("Duplicate column name"); } string text = keys.Last(); int columnIndex = ColumnHelper.GetColumnIndex(text); foreach (ExcelColumnInfo item in list) { if (item.ExcelColumnIndex.HasValue) { if (item.ExcelColumnIndex > columnIndex) { throw new ArgumentException($"ExcelColumnIndex {item.ExcelColumnIndex} over haeder max index {text}"); } if (item.ExcelColumnName == null) { throw new InvalidOperationException($"{item.Property.Info.DeclaringType.Name} {item.Property.Name}'s ExcelColumnIndex {item.ExcelColumnIndex} can't find excel column name"); } } } return list; } internal static string DescriptionAttr(Type type, object source) { FieldInfo field = type.GetField(source.ToString()); if (field == null) { return source.ToString(); } DescriptionAttribute[] array = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false); if (array != null && array.Length != 0) { return array[0].Description; } return source.ToString(); } private static IEnumerable<ExcelColumnInfo> ConvertToExcelCustomPropertyInfo(PropertyInfo[] props, Configuration configuration) { return from _ in props.Select(delegate(PropertyInfo p) { Type underlyingType = Nullable.GetUnderlyingType(p.PropertyType); ExcelColumnNameAttribute attribute = p.GetAttribute<ExcelColumnNameAttribute>(); Type excludeNullableType = underlyingType ?? p.PropertyType; string text = p.GetAttribute<ExcelFormatAttribute>()?.Format; ExcelColumnAttribute excelColumnAttribute = p.GetAttribute<ExcelColumnAttribute>(); DynamicExcelColumn dynamicExcelColumn = configuration?.DynamicColumns?.SingleOrDefault((DynamicExcelColumn _) => _.Key == p.Name); if (dynamicExcelColumn != null) { excelColumnAttribute = dynamicExcelColumn; } if (!p.GetAttributeValue((ExcelIgnoreAttribute x) => x.ExcelIgnore) && !p.GetAttributeValue((ExcelColumnAttribute x) => x.Ignore) && (excelColumnAttribute == null || !excelColumnAttribute.Ignore)) { int? num = ((excelColumnAttribute != null && excelColumnAttribute.Index > -1) ? new int?(excelColumnAttribute.Index) : null); ExcelColumnInfo obj = new ExcelColumnInfo { Property = new Property(p), ExcludeNullableType = excludeNullableType, Nullable = (underlyingType != null), ExcelColumnAliases = (attribute?.Aliases ?? excelColumnAttribute?.Aliases), ExcelColumnName = (attribute?.ExcelColumnName ?? p.GetAttribute<DisplayNameAttribute>()?.DisplayName ?? excelColumnAttribute?.Name ?? p.Name) }; ExcelColumnIndexAttribute attribute2 = p.GetAttribute<ExcelColumnIndexAttribute>(); obj.ExcelColumnIndex = ((attribute2 != null) ? new int?(attribute2.ExcelColumnIndex) : num); obj.ExcelIndexName = p.GetAttribute<ExcelColumnIndexAttribute>()?.ExcelXName ?? excelColumnAttribute?.IndexName; ExcelColumnWidthAttribute attribute3 = p.GetAttribute<ExcelColumnWidthAttribute>(); obj.ExcelColumnWidth = ((attribute3 != null) ? new double?(attribute3.ExcelColumnWidth) : excelColumnAttribute?.Width); obj.ExcelFormat = text ?? excelColumnAttribute?.Format; obj.ExcelFormatId = excelColumnAttribute?.FormatId ?? (-1); obj.ExcelColumnType = excelColumnAttribute?.Type ?? ColumnType.Value; obj.CustomFormatter = dynamicExcelColumn?.CustomFormatter; return obj; } return null; }) where _ != null select _; } private static IEnumerable<ExcelColumnInfo> GetExcelPropertyInfo(Type type, BindingFlags bindingFlags, Configuration configuration) { return ConvertToExcelCustomPropertyInfo(type.GetProperties(bindingFlags), configuration); } internal static ExcellSheetInfo GetExcellSheetInfo(Type type, Configuration configuration) { ExcellSheetInfo excellSheetInfo = new ExcellSheetInfo { Key = type.Name, ExcelSheetName = null, ExcelSheetState = SheetState.Visible }; if (type.GetCustomAttribute(typeof(ExcelSheetAttribute)) is ExcelSheetAttribute excelSheetAttribute) { excellSheetInfo.ExcelSheetName = excelSheetAttribute.Name ?? type.Name; excellSheetInfo.ExcelSheetState = excelSheetAttribute.State; } if (configuration is OpenXmlConfiguration openXmlConfiguration && openXmlConfiguration.DynamicSheets != null && openXmlConfiguration.DynamicSheets.Length != 0) { DynamicExcelSheet dynamicExcelSheet = openXmlConfiguration.DynamicSheets.SingleOrDefault((DynamicExcelSheet _) => _.Key == type.Name); if (dynamicExcelSheet != null) { excellSheetInfo.ExcelSheetName = dynamicExcelSheet.Name; excellSheetInfo.ExcelSheetState = dynamicExcelSheet.State; } } return excellSheetInfo; } internal static List<ExcelColumnInfo> GetDictionaryColumnInfo(IDictionary<string, object> dicString, IDictionary dic, Configuration configuration) { List<ExcelColumnInfo> props = new List<ExcelColumnInfo>(); if (dicString != null) { foreach (string key in dicString.Keys) { SetDictionaryColumnInfo(props, key, configuration); } } else { if (dic == null) { throw new NotSupportedException("SetDictionaryColumnInfo Error"); } foreach (object key2 in dic.Keys) { SetDictionaryColumnInfo(props, key2, configuration); } } return SortCustomProps(props); } internal static void SetDictionaryColumnInfo(List<ExcelColumnInfo> _props, object key, Configuration configuration) { ExcelColumnInfo excelColumnInfo = new ExcelColumnInfo(); excelColumnInfo.ExcelColumnName = key?.ToString(); excelColumnInfo.Key = key; bool flag = false; if (configuration.DynamicColumns != null && configuration.DynamicColumns.Length != 0) { DynamicExcelColumn dynamicExcelColumn = configuration.DynamicColumns.SingleOrDefault((DynamicExcelColumn _) => _.Key == key.ToString()); if (dynamicExcelColumn != null) { excelColumnInfo.Nullable = true; if (dynamicExcelColumn.Format != null) { excelColumnInfo.ExcelFormat = dynamicExcelColumn.Format; excelColumnInfo.ExcelFormatId = dynamicExcelColumn.FormatId; } if (dynamicExcelColumn.Aliases != null) { excelColumnInfo.ExcelColumnAliases = dynamicExcelColumn.Aliases; } if (dynamicExcelColumn.IndexName != null) { excelColumnInfo.ExcelIndexName = dynamicExcelColumn.IndexName; } excelColumnInfo.ExcelColumnIndex = dynamicExcelColumn.Index; if (dynamicExcelColumn.Name != null) { excelColumnInfo.ExcelColumnName = dynamicExcelColumn.Name; } flag = dynamicExcelColumn.Ignore; excelColumnInfo.ExcelColumnWidth = dynamicExcelColumn.Width; excelColumnInfo.ExcelColumnType = dynamicExcelColumn.Type; excelColumnInfo.CustomFormatter = dynamicExcelColumn.CustomFormatter; } } if (!flag) { _props.Add(excelColumnInfo); } } internal static bool TryGetTypeColumnInfo(Type type, Configuration configuration, out List<ExcelColumnInfo> props) { if (type == null) { props = null; return false; } if (type.IsValueType) { throw new NotImplementedException("MiniExcel not support only " + type.Name + " value generic type"); } if (type == typeof(string) || type == typeof(DateTime) || type == typeof(Guid)) { throw new NotImplementedException("MiniExcel not support only " + type.Name + " generic type"); } if (ValueIsNeededToDetermineProperties(type)) { props = null; return false; } props = type.GetSaveAsProperties(configuration); return true; } internal static List<ExcelColumnInfo> GetColumnInfoFromValue(object value, Configuration configuration) { if (!(value is IDictionary<string, object> dicString)) { if (value is IDictionary dic) { return GetDictionaryColumnInfo(null, dic, configuration); } return value.GetType().GetSaveAsProperties(configuration); } return GetDictionaryColumnInfo(dicString, null, configuration); } private static bool ValueIsNeededToDetermineProperties(Type type) { if (!(type == typeof(object)) && !typeof(IDictionary<string, object>).IsAssignableFrom(type)) { return typeof(IDictionary).IsAssignableFrom(type); } return true; } internal static ExcelColumnInfo GetColumnInfosFromDynamicConfiguration(string columnName, Configuration configuration) { ExcelColumnInfo excelColumnInfo = new ExcelColumnInfo { ExcelColumnName = columnName, Key = columnName }; if (configuration.DynamicColumns == null || configuration.DynamicColumns.Length == 0) { return excelColumnInfo; } DynamicExcelColumn dynamicExcelColumn = configuration.DynamicColumns.SingleOrDefault((DynamicExcelColumn _) => string.Equals(_.Key, columnName, StringComparison.OrdinalIgnoreCase)); if (dynamicExcelColumn == null || dynamicExcelColumn.Ignore) { return excelColumnInfo; } excelColumnInfo.Nullable = true; excelColumnInfo.ExcelIgnore = dynamicExcelColumn.Ignore; excelColumnInfo.ExcelColumnType = dynamicExcelColumn.Type; excelColumnInfo.ExcelColumnIndex = dynamicExcelColumn.Index; excelColumnInfo.ExcelColumnWidth = dynamicExcelColumn.Width; excelColumnInfo.CustomFormatter = dynamicExcelColumn.CustomFormatter; if (dynamicExcelColumn.Format != null) { excelColumnInfo.ExcelFormat = dynamicExcelColumn.Format; excelColumnInfo.ExcelFormatId = dynamicExcelColumn.FormatId; } if (dynamicExcelColumn.Aliases != null) { excelColumnInfo.ExcelColumnAliases = dynamicExcelColumn.Aliases; } if (dynamicExcelColumn.IndexName != null) { excelColumnInfo.ExcelIndexName = dynamicExcelColumn.IndexName; } if (dynamicExcelColumn.Name != null) { excelColumnInfo.ExcelColumnName = dynamicExcelColumn.Name; } return excelColumnInfo; } } internal static class DateTimeHelper { public const double OADateMinAsDouble = -657435.0; public const double OADateMaxAsDouble = 2958466.0; private const long TicksPerMillisecond = 10000L; private const long TicksPerSecond = 10000000L; private const long TicksPerMinute = 600000000L; private const long TicksPerHour = 36000000000L; private const long TicksPerDay = 864000000000L; private const int MillisPerSecond = 1000; private const int MillisPerMinute = 60000; private const int MillisPerHour = 3600000; private const int MillisPerDay = 86400000; private const int DaysPerYear = 365; private const int DaysPer4Years = 1461; private const int DaysPer100Years = 36524; private const int DaysPer400Years = 146097; private const int DaysTo1899 = 693593; private const int DaysTo10000 = 3652059; private const long MaxMillis = 315537897600000L; private const long DoubleDateOffset = 599264352000000000L; public static bool IsDateTimeFormat(string formatCode) { return new ExcelNumberFormat(formatCode).IsDateTimeFormat; } public static DateTime FromOADate(double d) { return new DateTime(DoubleDateToTicks(d), DateTimeKind.Unspecified); } internal static long DoubleDateToTicks(double value) { if (value >= 2958466.0 || value <= -657435.0) { throw new ArgumentException("Invalid OA Date"); } long num = (long)(value * 86400000.0 + ((value >= 0.0) ? 0.5 : (-0.5))); if (num < 0) { num -= num % 86400000 * 2; } num += 59926435200000L; if (num < 0 || num >= 315537897600000L) { throw new ArgumentException("OA Date out of range"); } return num * 10000; } public static double AdjustOADateTime(double value, bool date1904) { if (!date1904) { if (value >= 0.0 && value < 60.0) { return value + 1.0; } return value; } return value + 1462.0; } public static bool IsValidOADateTime(double value) { if (value > -657435.0) { return value < 2958466.0; } return false; } public static object ConvertFromOATime(double value, bool date1904) { double num = AdjustOADateTime(value, date1904); if (IsValidOADateTime(num)) { return FromOADate(num); } return value; } } internal static class DictionaryHelper { public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue) { if (!dictionary.TryGetValue(key, out var value)) { return defaultValue; } return value; } public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> defaultValueProvider) { if (!dictionary.TryGetValue(key, out var value)) { return defaultValueProvider(); } return value; } } internal class ExcelNumberFormat { public bool IsValid { get; } public string FormatString { get; } public bool IsDateTimeFormat { get; } public bool IsTimeSpanFormat { get; } internal List<Section> Sections { get; } public ExcelNumberFormat(string formatString) { bool syntaxError; List<Section> list = Parser.ParseSections(formatString, out syntaxError); IsValid = !syntaxError; FormatString = formatString; if (IsValid) { Sections = list; IsDateTimeFormat = Evaluator.GetFirstSection(Sections, SectionType.Date) != null; IsTimeSpanFormat = Evaluator.GetFirstSection(Sections, SectionType.Duration) != null; } else { Sections = new List<Section>(); } } } internal static class Evaluator { public static Section GetSection(List<Section> sections, object value) { if (!(value is string)) { if (value is DateTime) { _ = (DateTime)value; return GetFirstSection(sections, SectionType.Date); } if (!(value is TimeSpan timeSpan)) { if (!(value is double value2)) { if (!(value is int num)) { if (value is short num2) { return GetNumericSection(sections, num2); } return null; } return GetNumericSection(sections, num); } return GetNumericSection(sections, value2); } return GetNumericSection(sections, timeSpan.TotalDays); } if (sections.Count >= 4) { return sections[3]; } return null; } public static Section GetFirstSection(List<Section> sections, SectionType type) { foreach (Section section in sections) { if (section.Type == type) { return section; } } return null; } private static Section GetNumericSection(List<Section> sections, double value) { if (sections.Count < 3) { return null; } return sections[2]; } } internal enum SectionType { General, Number, Fraction, Exponential, Date, Duration, Text } internal class Section { public int SectionIndex { get; set; } public SectionType Type { get; set; } public List<string> GeneralTextDateDurationParts { get; set; } } internal class FractionSection { public List<string> IntegerPart { get; set; } public List<string> Numerator { get; set; } public List<string> DenominatorPrefix { get; set; } public List<string> Denominator { get; set; } public int DenominatorConstant { get; set; } public List<string> DenominatorSuffix { get; set; } public List<string> FractionSuffix { get; set; } public static bool TryParse(List<string> tokens, out FractionSection format) { List<string> list = null; List<string> tokens2 = null; for (int i = 0; i < tokens.Count; i++) { if (tokens[i] == "/") { list = tokens.GetRange(0, i); i++; tokens2 = tokens.GetRange(i, tokens.Count - i); break; } } if (list == null) { format = null; return false; } GetNumerator(list, out var integerPart, out var numeratorPart); if (!TryGetDenominator(tokens2, out var denominatorPrefix, out var denominatorPart, out var denominatorConstant, out var denominatorSuffix, out var fractionSuffix)) { format = null; return false; } format = new FractionSection { IntegerPart = integerPart, Numerator = numeratorPart, DenominatorPrefix = denominatorPrefix, Denominator = denominatorPart, DenominatorConstant = denominatorConstant, DenominatorSuffix = denominatorSuffix, FractionSuffix = fractionSuffix }; return true; } private static void GetNumerator(List<string> tokens, out List<string> integerPart, out List<string> numeratorPart) { bool flag = false; bool flag2 = false; bool flag3 = false; int num = -1; for (int num2 = tokens.Count - 1; num2 >= 0; num2--) { if (Token.IsPlaceholder(tokens[num2])) { flag = true; if (flag2) { flag3 = true; break; } } else if (flag && !flag2) { flag2 = true; num = num2 + 1; } } if (flag3) { integerPart = tokens.GetRange(0, num); numeratorPart = tokens.GetRange(num, tokens.Count - num); } else { integerPart = null; numeratorPart = tokens; } } private static bool TryGetDenominator(List<string> tokens, out List<string> denominatorPrefix, out List<string> denominatorPart, out int denominatorConstant, out List<string> denominatorSuffix, out List<string> fractionSuffix) { int i = 0; bool flag = false; bool flag2 = false; StringBuilder stringBuilder = new StringBuilder(); for (; i < tokens.Count; i++) { string token = tokens[i]; if (Token.IsPlaceholder(token)) { flag = true; break; } if (Token.IsDigit19(token)) { flag2 = true; break; } } if (!flag && !flag2) { denominatorPrefix = null; denominatorPart = null; denominatorConstant = 0; denominatorSuffix = null; fractionSuffix = null; return false; } int num = i; for (; i < tokens.Count; i++) { string text = tokens[i]; if (!flag || !Token.IsPlaceholder(text)) { if (!flag2 || !Token.IsDigit09(text)) { break; } stringBuilder.Append(text); } } int num2 = tokens.Count; while (num2 > i && !Token.IsPlaceholder(tokens[num2 - 1])) { num2--; } if (num > 0) { denominatorPrefix = tokens.GetRange(0, num); } else { denominatorPrefix = null; } if (flag2) { denominatorConstant = int.Parse(stringBuilder.ToString()); } else { denominatorConstant = 0; } denominatorPart = tokens.GetRange(num, i - num); if (i < num2) { denominatorSuffix = tokens.GetRange(i, num2 - i); } else { denominatorSuffix = null; } if (num2 < tokens.Count) { fractionSuffix = tokens.GetRange(num2, tokens.Count - num2); } else { fractionSuffix = null; } return true; } } internal class ExponentialSection { public List<string> BeforeDecimal { get; set; } public bool DecimalSeparator { get; set; } public List<string> AfterDecimal { get; set; } public string ExponentialToken { get; set; } public List<string> Power { get; set; } public static bool TryParse(List<string> tokens, out ExponentialSection format) { format = null; List<string> beforeDecimal; bool decimalSeparator; List<string> afterDecimal; int num = Parser.ParseNumberTokens(tokens, 0, out beforeDecimal, out decimalSeparator, out afterDecimal); if (num == 0) { return false; } int num2 = num; if (num2 < tokens.Count && Token.IsExponent(tokens[num2])) { string exponentialToken = tokens[num2]; num2++; format = new ExponentialSection { BeforeDecimal = beforeDecimal, DecimalSeparator = decimalSeparator, AfterDecimal = afterDecimal, ExponentialToken = exponentialToken, Power = tokens.GetRange(num2, tokens.Count - num2) }; return true; } return false; } } internal class DecimalSection { public bool ThousandSeparator { get; set; } public double ThousandDivisor { get; set; } public double PercentMultiplier { get; set; } public List<string> BeforeDecimal { get; set; } public bool DecimalSeparator { get; set; } public List<string> AfterDecimal { get; set; } public static bool TryParse(List<string> tokens, out DecimalSection format) { if (Parser.ParseNumberTokens(tokens, 0, out var beforeDecimal, out var decimalSeparator, out var afterDecimal) == tokens.Count) { bool thousandSeparator; double trailingCommasDivisor = GetTrailingCommasDivisor(tokens, out thousandSeparator); double percentMultiplier = GetPercentMultiplier(tokens); format = new DecimalSection { BeforeDecimal = beforeDecimal, DecimalSeparator = decimalSeparator, AfterDecimal = afterDecimal, PercentMultiplier = percentMultiplier, ThousandDivisor = trailingCommasDivisor, ThousandSeparator = thousandSeparator }; return true; } format = null; return false; } private static double GetPercentMultiplier(List<string> tokens) { foreach (string token in tokens) { if (token == "%") { return 100.0; } } return 1.0; } private static double GetTrailingCommasDivisor(List<string> tokens, out bool thousandSeparator) { bool flag = false; double num = 1.0; for (int i = 0; i < tokens.Count; i++) { int num2 = tokens.Count - 1 - i; string text = tokens[num2]; if (!flag) { if (!Token.IsPlaceholder(text)) { continue; } for (int j = num2 + 1; j < tokens.Count; j++) { text = tokens[j]; if (!(text == ",")) { break; } num *= 1000.0; } flag = true; } else if (text == ",") { thousandSeparator = true; return num; } } thousandSeparator = false; return num; } } internal class ExcelDateTime { private static DateTime Excel1900LeapMinDate = new DateTime(1900, 2, 28); private static DateTime Excel1900LeapMaxDate = new DateTime(1900, 3, 1); private static DateTime Excel1900ZeroethMinDate = new DateTime(1899, 12, 30); private static DateTime Excel1900ZeroethMaxDate = new DateTime(1899, 12, 31); private const long TicksPerMillisecond = 10000L; private const long TicksPerSecond = 10000000L; private const long TicksPerMinute = 600000000L; private const long TicksPerHour = 36000000000L; private const long TicksPerDay = 864000000000L; private const int MillisPerSecond = 1000; private const int MillisPerMinute = 60000; private const int MillisPerHour = 3600000; private const int MillisPerDay = 86400000; private const int DaysPerYear = 365; private const int DaysPer4Years = 1461; private const int DaysPer100Years = 36524; private const int DaysPer400Years = 146097; private const int DaysTo1899 = 693593; private const long DoubleDateOffset = 599264352000000000L; public DateTime AdjustedDateTime { get; } public int AdjustDaysPost { get; } public int Year => AdjustedDateTime.Year; public int Month => AdjustedDateTime.Month; public int Day => AdjustedDateTime.Day + AdjustDaysPost; public int Hour => AdjustedDateTime.Hour; public int Minute => AdjustedDateTime.Minute; public int Second => AdjustedDateTime.Second; public int Millisecond => AdjustedDateTime.Millisecond; public DayOfWeek DayOfWeek => AdjustedDateTime.DayOfWeek; public ExcelDateTime(double numericDate, bool isDate1904) { if (isDate1904) { numericDate += 1462.0; AdjustedDateTime = new DateTime(DoubleDateToTicks(numericDate), DateTimeKind.Unspecified); return; } DateTime dateTime = new DateTime(DoubleDateToTicks(numericDate), DateTimeKind.Unspecified); if (dateTime < Excel1900ZeroethMinDate) { AdjustDaysPost = 0; AdjustedDateTime = dateTime.AddDays(2.0); } else if (dateTime < Excel1900ZeroethMaxDate) { AdjustDaysPost = -1; AdjustedDateTime = dateTime.AddDays(2.0); } else if (dateTime < Excel1900LeapMinDate) { AdjustDaysPost = 0; AdjustedDateTime = dateTime.AddDays(1.0); } else if (dateTime < Excel1900LeapMaxDate) { AdjustDaysPost = 1; AdjustedDateTime = dateTime; } else { AdjustDaysPost = 0; AdjustedDateTime = dateTime; } } public ExcelDateTime(DateTime value) { AdjustedDateTime = value; AdjustDaysPost = 0; } public string ToString(string numberFormat, CultureInfo culture) { return AdjustedDateTime.ToString(numberFormat, culture); } public static bool TryConvert(object value, bool isDate1904, CultureInfo culture, out ExcelDateTime result) { if (value is double numericDate) { result = new ExcelDateTime(numericDate, isDate1904); return true; } if (value is int num) { result = new ExcelDateTime(num, isDate1904); return true; } if (value is short num2) { result = new ExcelDateTime(num2, isDate1904); return true; } if (value is DateTime value2) { result = new ExcelDateTime(value2); return true; } result = null; return false; } internal static long DoubleDateToTicks(double value) { long num = (long)(value * 86400000.0 + ((value >= 0.0) ? 0.5 : (-0.5))); if (num < 0) { num -= num % 86400000 * 2; } num += 59926435200000L; return num * 10000; } } internal static class Parser { public static List<Section> ParseSections(string formatString, out bool syntaxError) { Tokenizer reader = new Tokenizer(formatString); List<Section> list = new List<Section>(); syntaxError = false; while (true) { bool syntaxError2; Section section = ParseSection(reader, list.Count, out syntaxError2); if (syntaxError2) { syntaxError = true; } if (section == null) { break; } list.Add(section); } return list; } private static Section ParseSection(Tokenizer reader, int index, out bool syntaxError) { bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; bool flag5 = false; List<string> list = new List<string>(); syntaxError = false; string text; while ((text = ReadToken(reader, out syntaxError)) != null && !(text == ";")) { flag5 |= Token.IsPlaceholder(text); if (Token.IsDatePart(text)) { flag = flag || true; flag2 |= Token.IsDurationPart(text); list.Add(text); } else { list.Add(text); } } if (syntaxError || list.Count == 0) { return null; } if ((flag && (flag3 || flag4)) || (flag3 && (flag || flag4)) || (flag4 && (flag3 || flag))) { syntaxError = true; return null; } FractionSection format = null; ExponentialSection format2 = null; DecimalSection format3 = null; List<string> result = null; SectionType type; if (flag) { type = ((!flag2) ? SectionType.Date : SectionType.Duration); ParseMilliseconds(list, out result); } else if (flag3) { type = SectionType.General; result = list; } else if (flag4 || !flag5) { type = SectionType.Text; result = list; } else if (FractionSection.TryParse(list, out format)) { type = SectionType.Fraction; } else if (ExponentialSection.TryParse(list, out format2)) { type = SectionType.Exponential; } else { if (!DecimalSection.TryParse(list, out format3)) { syntaxError = true; return null; } type = SectionType.Number; } return new Section { Type = type, SectionIndex = index, GeneralTextDateDurationParts = result }; } internal static int ParseNumberTokens(List<string> tokens, int startPosition, out List<string> beforeDecimal, out bool decimalSeparator, out List<string> afterDecimal) { beforeDecimal = null; afterDecimal = null; decimalSeparator = false; List<string> list = new List<string>(); int num = 0; for (num = 0; num < tokens.Count; num++) { string text = tokens[num]; if (text == "." && beforeDecimal == null) { decimalSeparator = true; beforeDecimal = tokens.GetRange(0, num); list = new List<string>(); } else if (Token.IsNumberLiteral(text)) { list.Add(text); } else if (!text.StartsWith("[")) { break; } } if (list.Count > 0) { if (beforeDecimal != null) { afterDecimal = list; } else { beforeDecimal = list; } } return num; } private static void ParseMilliseconds(List<string> tokens, out List<string> result) { result = new List<string>(); for (int i = 0; i < tokens.Count; i++) { string text = tokens[i]; if (text == ".") { int num = 0; while (i + 1 < tokens.Count && tokens[i + 1] == "0") { i++; num++; } if (num > 0) { result.Add("." + new string('0', num)); } else { result.Add("."); } } else { result.Add(text); } } } private static string ReadToken(Tokenizer reader, out bool syntaxError) { int position = reader.Position; if (ReadLiteral(reader) || reader.ReadEnclosed('[', ']') || reader.ReadOneOf("#?,!&%+-$€£0123456789{}():;/.@ ") || reader.ReadString("e+", ignoreCase: true) || reader.ReadString("e-", ignoreCase: true) || reader.ReadString("General", ignoreCase: true) || reader.ReadString("am/pm", ignoreCase: true) || reader.ReadString("a/p", ignoreCase: true) || reader.ReadOneOrMore(121) || reader.ReadOneOrMore(89) || reader.ReadOneOrMore(109) || reader.ReadOneOrMore(77) || reader.ReadOneOrMore(100) || reader.ReadOneOrMore(68) || reader.ReadOneOrMore(104) || reader.ReadOneOrMore(72) || reader.ReadOneOrMore(115) || reader.ReadOneOrMore(83) || reader.ReadOneOrMore(103) || reader.ReadOneOrMore(71)) { syntaxError = false; int length = reader.Position - position; return reader.Substring(position, length); } syntaxError = reader.Position < reader.Length; return null; } private static bool ReadLiteral(Tokenizer reader) { if (reader.Peek() == 92 || reader.Peek() == 42 || reader.Peek() == 95) { reader.Advance(2); return true; } if (reader.ReadEnclosed('"', '"')) { return true; } return false; } } internal class Tokenizer { private string formatString; private int formatStringPosition; public int Position => formatStringPosition; public int Length => formatString?.Length ?? 0; public Tokenizer(string fmt) { formatString = fmt; } public string Substring(int startIndex, int length) { return formatString.Substring(startIndex, length); } public int Peek(int offset = 0) { if (formatStringPosition + offset >= Length) { return -1; } return formatString[formatStringPosition + offset]; } public int PeekUntil(int startOffset, int until) { int num = startOffset; while (true) { int num2 = Peek(num++); if (num2 == -1) { break; } if (num2 == until) { return num - startOffset; } } return 0; } public bool PeekOneOf(int offset, string s) { foreach (char c in s) { if (Peek(offset) == c) { return true; } } return false; } public void Advance(int characters = 1) { formatStringPosition = Math.Min(formatStringPosition + characters, formatString.Length); } public bool ReadOneOrMore(int c) { if (Peek() != c) { return false; } while (Peek() == c) { Advance(); } return true; } public bool ReadOneOf(string s) { if (PeekOneOf(0, s)) { Advance(); return true; } return false; } public bool ReadString(string s, bool ignoreCase = false) { if (formatStringPosition + s.Length > Length) { return false; } for (int i = 0; i < s.Length; i++) { char c = s[i]; char c2 = (char)Peek(i); if (ignoreCase) { if (char.ToLower(c) != char.ToLower(c2)) { return false; } } else if (c != c2) { return false; } } Advance(s.Length); return true; } public bool ReadEnclosed(char open, char close) { if (Peek() == open) { int num = PeekUntil(1, close); if (num > 0) { Advance(1 + num); return true; } } return false; } } internal static class Token { public static bool IsExponent(string token) { if (string.Compare(token, "e+", StringComparison.OrdinalIgnoreCase) != 0) { return string.Compare(token, "e-", StringComparison.OrdinalIgnoreCase) == 0; } return true; } public static bool IsLiteral(string token) { if (!token.StartsWith("_", StringComparison.Ordinal) && !token.StartsWith("\\", StringComparison.Ordinal) && !token.StartsWith("\"", StringComparison.Ordinal) && !token.StartsWith("*", StringComparison.Ordinal)) { switch (token) { default: return token == " "; case ",": case "!": case "&": case "%": case "+": case "-": case "$": case "€": case "£": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": case "{": case "}": case "(": case ")": break; } } return true; } public static bool IsNumberLiteral(string token) { if (!IsPlaceholder(token) && !IsLiteral(token)) { return token == "."; } return true; } public static bool IsPlaceholder(string token) { if (!(token == "0") && !(token == "#")) { return token == "?"; } return true; } public static bool IsGeneral(string token) { return string.Compare(token, "general", StringComparison.OrdinalIgnoreCase) == 0; } public static bool IsDatePart(string token) { if (!token.StartsWith("y", StringComparison.OrdinalIgnoreCase) && !token.StartsWith("m", StringComparison.OrdinalIgnoreCase) && !token.StartsWith("d", StringComparison.OrdinalIgnoreCase) && !token.StartsWith("s", StringComparison.OrdinalIgnoreCase) && !token.StartsWith("h", StringComparison.OrdinalIgnoreCase) && (!token.StartsWith("g", StringComparison.OrdinalIgnoreCase) || IsGeneral(token)) && string.Compare(token, "am/pm", StringComparison.OrdinalIgnoreCase) != 0 && string.Compare(token, "a/p", StringComparison.OrdinalIgnoreCase) != 0) { return IsDurationPart(token); } return true; } public static bool IsDurationPart(string token) { if (!token.StartsWith("[h", StringComparison.OrdinalIgnoreCase) && !token.StartsWith("[m", StringComparison.OrdinalIgnoreCase)) { return token.StartsWith("[s", StringComparison.OrdinalIgnoreCase); } return true; } public static bool IsDigit09(string token) { if (!(token == "0")) { return IsDigit19(token); } return true; } public static bool IsDigit19(string token) { if (token != null) { int length = token.Length; if (length == 1) { switch (token[0]) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return true; } } } return false; } } public static class ExcelTypeHelper { internal static ExcelType GetExcelType(string filePath, ExcelType excelType) { if (excelType != ExcelType.UNKNOWN) { return excelType; } string text = Path.GetExtension(filePath).ToLowerInvariant(); switch (text) { case ".csv": return ExcelType.CSV; case ".xlsx": case ".xlsm": return ExcelType.XLSX; default: throw new NotSupportedException("Extension : " + text + " not suppprt, or you can specify exceltype."); } } internal static ExcelType GetExcelType(Stream stream, ExcelType excelType) { if (excelType != ExcelType.UNKNOWN) { return excelType; } byte[] array = new byte[8]; stream.Seek(0L, SeekOrigin.Begin); stream.Read(array, 0, array.Length); stream.Seek(0L, SeekOrigin.Begin); if (array[0] == 80 && array[1] == 75) { return ExcelType.XLSX; } throw new NotSupportedException("Stream cannot know the file type, please specify ExcelType manually"); } } internal static class FileHelper { public static FileStream OpenSharedRead(string path) { return File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); } } internal class ImageHelper { public enum ImageFormat { bmp, jpg, gif, tiff, png, unknown } public static ImageFormat GetImageFormat(byte[] bytes) { byte[] value = new byte[2] { 66, 77 }; byte[] value2 = new byte[3] { 71, 73, 70 }; byte[] value3 = new byte[4] { 137, 80, 78, 71 }; byte[] value4 = new byte[3] { 73, 73, 42 }; byte[] value5 = new byte[3] { 77, 77, 42 }; byte[] value6 = new byte[4] { 255, 216, 255, 224 }; byte[] value7 = new byte[4] { 255, 216, 255, 225 }; if (bytes.StartsWith(value)) { return ImageFormat.bmp; } if (bytes.StartsWith(value2)) { return ImageFormat.gif; } if (bytes.StartsWith(value3)) { return ImageFormat.png; } if (bytes.StartsWith(value4)) { return ImageFormat.tiff; } if (bytes.StartsWith(value5)) { return ImageFormat.tiff; } if (bytes.StartsWith(value6)) { return ImageFormat.jpg; } if (bytes.StartsWith(value7)) { return ImageFormat.jpg; } return ImageFormat.unknown; } } public static class IEnumerableHelper { public static bool StartsWith<T>(this IList<T> span, IList<T> value) where T : IEquatable<T> { if (value.Count == 0) { return true; } int num = span.Take(value.Count).Count(); if (num != value.Count) { return false; } for (int i = 0; i < num; i++) { if (!span[i].Equals(value[i])) { return false; } } return true; } } internal static class ReferenceHelper { public static string GetCellNumber(string cell) { string text = string.Empty; for (int i = 0; i < cell.Length; i++) { if (char.IsDigit(cell[i])) { text += cell[i]; } } return text; } public static string GetCellLetter(string cell) { string text = string.Empty; for (int i = 0; i < cell.Length; i++) { if (char.IsLetter(cell[i])) { text += cell[i]; } } return text; } public static Tuple<int, int> ConvertCellToXY(string cell) { int num = 0; string cellLetter = GetCellLetter(cell); for (int i = 0; i < cellLetter.Length; i++) { num = num * 26 + " ABCDEFGHIJKLMNOPQRSTUVWXYZ".IndexOf(cellLetter[i]); } string cellNumber = GetCellNumber(cell); return Tuple.Create(num, int.Parse(cellNumber)); } public static string ConvertXyToCell(int x, int y
BepInEx/plugins/com.binbin.DivinationLogger.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using MiniExcelLibs; using MiniExcelLibs.OpenXml; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.binbin.DivinationLogger")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0+4152efad598808e0268af6d8f82091eb4244cc43")] [assembly: AssemblyProduct("DivinationLogger")] [assembly: AssemblyTitle("com.binbin.DivinationLogger")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DivinationLogger { [HarmonyPatch] public class DivinationLogger { [HarmonyPostfix] [HarmonyPatch(typeof(AtOManager), "GoToTown")] public static void GoToTownPostfix(AtOManager __instance) { Plugin.LogDebug("GoToTownPostfix"); if (Plugin.LogToLogOutput.Value) { LogDivinations(__instance); } WriteDivinationsToFile(__instance); } public static int GetDivinationTier(int divinationIndex) { Plugin.LogDebug("Divination Tier: " + divinationIndex); AtOManager instance = AtOManager.Instance; if ((Object)(object)instance == (Object)null) { Plugin.LogDebug("AtOManager is null"); return 0; } Dictionary<int, int> dictionary = new Dictionary<int, int>(); dictionary.Add(0, 2); dictionary.Add(1, 5); dictionary.Add(2, 6); dictionary.Add(3, 8); dictionary.Add(4, 10); return dictionary.ContainsKey(divinationIndex) ? dictionary[divinationIndex] : 0; } public static void LogDivinations(AtOManager atOManager) { Plugin.LogDebug("LogDivinations"); int divinationsNumber = atOManager.divinationsNumber; int num = ((atOManager.GetTownTier() == 3) ? 2 : Math.Min(atOManager.GetTownTier(), 1)); if (atOManager.GetTownTier() == 2) { num--; } int num2 = 3; int value = Plugin.DivinationsToLog.Value; Dictionary<int, string> dictionary = new Dictionary<int, string>(); dictionary.Add(0, "Fast"); dictionary.Add(1, "Basic"); dictionary.Add(2, "Advanced"); dictionary.Add(3, "Premium"); dictionary.Add(4, "Supreme"); if (atOManager.GetTeam() == null) { Plugin.LogDebug("Team is null"); return; } Hero[] team = atOManager.GetTeam(); for (int i = 0; i < num2; i++) { for (int j = 0; j < value; j++) { int num3 = j + divinationsNumber; Plugin.LogDebug($"Divination {num3} {dictionary[num + i]}"); Dictionary<int, string[]> divinationDictForOneDivination = GetDivinationDictForOneDivination(atOManager, num + i, num3); if (divinationDictForOneDivination == null) { Plugin.LogDebug("cardsByOrder is null"); return; } foreach (KeyValuePair<int, string[]> item in divinationDictForOneDivination) { if (item.Value == null || item.Value.Length == 0 || item.Key >= team.Length) { Plugin.LogDebug("Row is null"); return; } List<string> list = new List<string>(); for (int k = 0; k < item.Value.Length; k++) { CardData cardData = Globals.Instance.GetCardData(item.Value[k], false); if ((Object)(object)cardData == (Object)null) { list.Add(""); } else { list.Add(GetCardName(cardData)); } } Hero obj = team[item.Key]; string arg = ((obj == null) ? null : ((Character)obj).SourceName?.ToString()) ?? "Unknown"; Plugin.LogDebug(string.Format("Hero {0}, {1}. Cards: {2}", item.Key, arg, string.Join(", ", list))); } } } } public static void WriteDivinationsToFile(AtOManager atOManager) { Plugin.LogDebug("WriteDivinationsToFile"); int divinationsNumber = atOManager.divinationsNumber; int num = Math.Min(Math.Max(atOManager.GetTownTier() - 1, 0), 2); int num2 = 3; int value = Plugin.DivinationsToLog.Value; Dictionary<int, string> dictionary = new Dictionary<int, string>(); dictionary.Add(0, "Fast"); dictionary.Add(1, "Basic"); dictionary.Add(2, "Advanced"); dictionary.Add(3, "Premium"); dictionary.Add(4, "Supreme"); List<string> list = new List<string>(1) { "Divination" }; List<List<string>> list2 = new List<List<string>>(); list2.Add(list); if (atOManager.GetTeam() == null) { Plugin.LogDebug("Team is null"); return; } Hero[] team = atOManager.GetTeam(); bool flag = true; for (int i = 0; i < num2; i++) { int num3 = 4; string arg = dictionary[num + i]; for (int j = 0; j < num3; j++) { if (Plugin.AddSpaces.Value && flag) { list.Add(""); flag = false; } list.Add($"{arg}: Card {j + 1}"); } flag = true; } for (int k = 0; k < value; k++) { List<List<string>> list3 = new List<List<string>>(); for (int l = 0; l < team.Count(); l++) { list3.Add(new List<string>()); } flag = true; for (int m = 0; m < num2; m++) { int num4 = k + divinationsNumber; Plugin.LogDebug($"Divination {num4} {dictionary[num + m]}"); Dictionary<int, string[]> divinationDictForOneDivination = GetDivinationDictForOneDivination(atOManager, num + m, num4); foreach (KeyValuePair<int, string[]> item3 in divinationDictForOneDivination) { int key = item3.Key; List<string> list4 = new List<string>(); for (int n = 0; n < 4; n++) { if (Plugin.AddSpaces.Value && flag) { list4.Add(""); flag = false; } if (n >= item3.Value.Length) { list4.Add(""); continue; } CardData cardData = Globals.Instance.GetCardData(item3.Value[n], false); if ((Object)(object)cardData == (Object)null) { list4.Add(""); } else { list4.Add(GetCardName(cardData)); } } flag = true; if (m == 0) { string text = $"D{num4 + 1}: "; Hero obj = team[key]; string item = text + (((obj == null) ? null : ((Character)obj).SourceName?.ToString()) ?? "Missing Hero"); list4.Insert(0, item); } list3[key].AddRange(list4); } } int count = 0; foreach (List<string> item4 in list3) { list2.Add(item4); count = item4.Count(); } if (Plugin.AddSpaces.Value) { List<string> item2 = Enumerable.Repeat("", count).ToList(); list2.Add(item2); } } SaveDivinationsToFile(atOManager, list2); } public static void SaveDivinationsToFile(AtOManager atOManager, List<List<string>> divinationResults) { string path; if (Plugin.AbsoluteFolderPath.Value == "" || Plugin.AbsoluteFolderPath.Value == null) { string directoryName = Path.GetDirectoryName(SaveManager.PathSaveGameTurn(0)); path = ((Plugin.SaveFolder.Value == "" || Plugin.SaveFolder.Value == null) ? Path.Combine(directoryName, atOManager.GetGameId()) : Path.Combine(directoryName, Plugin.SaveFolder.Value)); } else { path = Plugin.AbsoluteFolderPath.Value; } string path2 = string.Format("DivinationResults_Act_{0}.csv", atOManager.GetActNumberForText("")); string path3 = string.Format("DivinationResults_Act_{0}.xlsx", atOManager.GetActNumberForText("")); if (Plugin.SaveToCSV.Value) { WriteDataToCSV(divinationResults, Path.Combine(path, path2)); } if (Plugin.SaveToExcel.Value) { WriteDataToExcel(divinationResults, Path.Combine(path, path3)); } } public static Dictionary<int, string[]> GetDivinationDictForOneDivination(AtOManager atOManager, int tierNum, int ndivinations) { //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Invalid comparison between Unknown and I4 //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Invalid comparison between Unknown and I4 //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Invalid comparison between Unknown and I4 //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Invalid comparison between Unknown and I4 //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Invalid comparison between Unknown and I4 //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032e: Invalid comparison between Unknown and I4 //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Invalid comparison between Unknown and I4 //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Invalid comparison between Unknown and I4 Random.InitState(Functions.GetDeterministicHashCode(AtOManager.Instance.GetGameId() + "_" + AtOManager.Instance.mapVisitedNodes.Count + "_" + AtOManager.Instance.currentMapNode + "_" + ndivinations)); TierRewardData tierRewardData = Globals.Instance.GetTierRewardData(GetDivinationTier(tierNum)); Dictionary<int, string[]> dictionary = new Dictionary<int, string[]>(); int num = ((tierNum <= 1) ? 3 : 4); Hero[] team = AtOManager.Instance.GetTeam(); if ((Object)(object)tierRewardData != (Object)null) { TierRewardData val = tierRewardData; int num2 = val.TierNum; AtOManager.Instance.currentRewardTier = num2; if (num2 < 0) { num2 = 0; } val = Globals.Instance.GetTierRewardData(num2); TierRewardData val2 = ((num2 <= 0) ? val : Globals.Instance.GetTierRewardData(num2 - 1)); CardData val3 = null; for (int i = 0; i < team.Length; i++) { if (team[i] == null || (Object)(object)((Character)team[i]).HeroData == (Object)null) { dictionary[i] = new string[3] { "", "", "" }; continue; } Hero val4 = team[i]; CardClass result = (CardClass)11; Enum.TryParse<CardClass>(Enum.GetName(typeof(HeroClass), ((Character)val4).HeroData.HeroClass), out result); CardClass result2 = (CardClass)11; Enum.TryParse<CardClass>(Enum.GetName(typeof(HeroClass), ((Character)val4).HeroData.HeroSubClass.HeroClassSecondary), out result2); int num3 = num; if (num == 3 && (int)result2 != 11) { num3 = 4; } string[] array = new string[num3]; List<string> list = Globals.Instance.CardListNotUpgradedByClass[result]; List<string> list2 = (((int)result2 == 11) ? new List<string>() : Globals.Instance.CardListNotUpgradedByClass[result2]); for (int j = 0; j < num3; j++) { TierRewardData val5 = ((j != 0) ? val2 : val); int num4 = Random.Range(0, 100); bool flag = true; while (flag) { flag = false; bool flag2 = false; while (!flag2) { flag = false; val3 = Globals.Instance.GetCardData((j < 2 || (int)result2 == 11) ? list[Random.Range(0, list.Count)] : list2[Random.Range(0, list2.Count)], false); if (flag) { continue; } if (num4 < val5.Common) { if ((int)val3.CardRarity == 0) { flag2 = true; } } else if (num4 < val5.Common + val5.Uncommon) { if ((int)val3.CardRarity == 1) { flag2 = true; } } else if (num4 < val5.Common + val5.Uncommon + val5.Rare) { if ((int)val3.CardRarity == 2) { flag2 = true; } } else if (num4 < val5.Common + val5.Uncommon + val5.Rare + val5.Epic) { if ((int)val3.CardRarity == 3) { flag2 = true; } } else if ((int)val3.CardRarity == 4) { flag2 = true; } } int num5 = Random.Range(0, 100); string id = val3.Id; val3 = Globals.Instance.GetCardData(Functions.GetCardByRarity(num5, val3, false), false); if ((Object)(object)val3 == (Object)null) { flag = true; continue; } for (int k = 0; k < array.Length; k++) { if (array[k] == val3.Id) { flag = true; break; } } } array[j] = val3.Id; } dictionary[i] = Functions.ShuffleArray<string>(array); } return dictionary; } Plugin.LogDebug("No townDivinationTier"); return null; } public static void WriteDataToCSV(List<List<string>> data, string filePath) { Plugin.LogDebug("WriteListToCsv"); try { StringBuilder stringBuilder = new StringBuilder(); foreach (List<string> datum in data) { stringBuilder.AppendLine(string.Join(",", datum.Select((string field) => (field.Contains(",") || field.Contains("\"")) ? ("\"" + field.Replace("\"", "\"\"") + "\"") : field))); } string directoryName = Path.GetDirectoryName(filePath); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllText(filePath, stringBuilder.ToString()); Plugin.LogDebug("CSV file successfully created at: " + filePath); } catch (Exception ex) { Plugin.LogError("An error occurred: " + ex.Message); } } public static void WriteDataToExcel(List<List<string>> data, string filePath) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown Plugin.LogDebug("WriteListToExcel"); List<string> list = data.FirstOrDefault(); if (list == null) { Plugin.LogError("headerRow is empty or null"); return; } List<Dictionary<string, object>> list2 = new List<Dictionary<string, object>>(); for (int i = 1; i < data.Count; i++) { List<string> list3 = data[i]; Dictionary<string, object> dictionary = new Dictionary<string, object>(); for (int j = 0; j < list.Count && j < list3.Count; j++) { dictionary.Add(list[j], list3[j]); } list2.Add(dictionary); } if (Plugin.AddFormatting.Value) { OpenXmlConfiguration val = new OpenXmlConfiguration { FastMode = true, EnableAutoWidth = true, FreezeColumnCount = 1, FreezeRowCount = 1 }; MiniExcel.SaveAs(filePath, (object)list2, true, "Sheet1", (ExcelType)2, (IConfiguration)(object)val, false); } Plugin.LogDebug("Excel file created at: " + filePath); } public static string GetCardName(CardData cardData) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Invalid comparison between Unknown and I4 string text = cardData.CardName; if ((int)cardData.CardUpgraded == 1) { text += " (Blue)"; } else if ((int)cardData.CardUpgraded == 2) { text += " (Yellow)"; } else if ((int)cardData.CardUpgraded == 3) { text += " (Corrupted)"; } return text; } } [BepInPlugin("com.binbin.DivinationLogger", "DivinationLogger", "1.2.0")] [BepInProcess("AcrossTheObelisk.exe")] public class Plugin : BaseUnityPlugin { internal int ModDate = int.Parse(DateTime.Today.ToString("yyyyMMdd")); private readonly Harmony harmony = new Harmony("com.binbin.DivinationLogger"); internal static ManualLogSource Log; public static string debugBase = "com.binbin.DivinationLogger "; public static ConfigEntry<bool> EnableMod { get; set; } public static ConfigEntry<bool> EnableDebug { get; set; } public static ConfigEntry<string> SaveFolder { get; set; } public static ConfigEntry<bool> SaveToCSV { get; set; } public static ConfigEntry<bool> SaveToExcel { get; set; } public static ConfigEntry<bool> LogToLogOutput { get; set; } public static ConfigEntry<string> AbsoluteFolderPath { get; set; } public static ConfigEntry<int> DivinationsToLog { get; set; } public static ConfigEntry<bool> AddSpaces { get; set; } public static ConfigEntry<bool> AddFormatting { get; set; } private void Awake() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0047: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0078: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00a9: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00da: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_010b: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_0140: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown //IL_0175: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_01a7: Expected O, but got Unknown //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Expected O, but got Unknown //IL_01d8: Expected O, but got Unknown //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_0209: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"com.binbin.DivinationLogger 1.2.0 has loaded!"); EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("DivinationLogger", "Enable Mod"), true, new ConfigDescription("If false, disables the mod. Restart the game upon changing this setting.", (AcceptableValueBase)null, Array.Empty<object>())); EnableDebug = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("DivinationLogger", "Enable Debug"), true, new ConfigDescription("If true, Enables Debug Logging.", (AcceptableValueBase)null, Array.Empty<object>())); LogToLogOutput = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("DivinationLogger", "Log to LogOutput"), false, new ConfigDescription("If true, logs the divinations to the LogOutput.", (AcceptableValueBase)null, Array.Empty<object>())); SaveToCSV = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("DivinationLogger", "Save to CSV"), true, new ConfigDescription("If true, saves the divinations as a csv file.", (AcceptableValueBase)null, Array.Empty<object>())); SaveToExcel = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("DivinationLogger", "Save to Excel"), false, new ConfigDescription("If true, saves the divinations as an Excel file.", (AcceptableValueBase)null, Array.Empty<object>())); SaveFolder = ((BaseUnityPlugin)this).Config.Bind<string>(new ConfigDefinition("DivinationLogger", "Save Folder"), "", new ConfigDescription("Folder to Save to, if left blank, will write to the default save folder/your current seed", (AcceptableValueBase)null, Array.Empty<object>())); AbsoluteFolderPath = ((BaseUnityPlugin)this).Config.Bind<string>(new ConfigDefinition("DivinationLogger", "Absolute Folder Path"), "", new ConfigDescription("Absolute FilePath to save to. If left blank, will default to Save Folder. Overrides Save Folder", (AcceptableValueBase)null, Array.Empty<object>())); DivinationsToLog = ((BaseUnityPlugin)this).Config.Bind<int>(new ConfigDefinition("DivinationLogger", "Number of Divinations"), 10, new ConfigDescription("The number of divinations that will be automatically logged whenever you enter town.", (AcceptableValueBase)null, Array.Empty<object>())); AddSpaces = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("DivinationLogger", "Add Spaces to File"), false, new ConfigDescription("Adds blank rows/columns in between the divinations and divination types", (AcceptableValueBase)null, Array.Empty<object>())); AddFormatting = ((BaseUnityPlugin)this).Config.Bind<bool>(new ConfigDefinition("DivinationLogger", "Add Formatting to Excel"), false, new ConfigDescription("Adds formatting, coloring cells if they are upgraded, and adding borders.", (AcceptableValueBase)null, Array.Empty<object>())); if (EnableMod.Value) { LogDebug("Excuting Patches"); harmony.PatchAll(); } } internal static void LogDebug(string msg) { if (EnableDebug.Value) { Log.LogDebug((object)(debugBase + msg)); } } internal static void LogInfo(string msg) { Log.LogInfo((object)(debugBase + msg)); } internal static void LogError(string msg) { Log.LogError((object)(debugBase + msg)); } } public static class PluginInfo { public const string PLUGIN_GUID = "com.binbin.DivinationLogger"; public const string PLUGIN_NAME = "DivinationLogger"; public const string PLUGIN_VERSION = "1.2.0"; } }
BepInEx/plugins/Microsoft.Bcl.AsyncInterfaces.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading.Tasks; using System.Threading.Tasks.Sources; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: AssemblyMetadata("PreferInbox", "True")] [assembly: AssemblyDefaultAlias("Microsoft.Bcl.AsyncInterfaces")] [assembly: CLSCompliant(true)] [assembly: AssemblyMetadata("IsTrimmable", "True")] [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] [assembly: AssemblyDescription("Provides the IAsyncEnumerable<T> and IAsyncDisposable interfaces and helper types for .NET Standard 2.0. This package is not required starting with .NET Standard 2.1 and .NET Core 3.0.")] [assembly: AssemblyFileVersion("9.0.325.11113")] [assembly: AssemblyInformationalVersion("9.0.3+831d23e56149cd59c40fc00c7feb7c5334bd19c4")] [assembly: AssemblyProduct("Microsoft® .NET")] [assembly: AssemblyTitle("Microsoft.Bcl.AsyncInterfaces")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")] [assembly: AssemblyVersion("9.0.0.3")] [assembly: TypeForwardedTo(typeof(IAsyncEnumerable<>))] [assembly: TypeForwardedTo(typeof(IAsyncEnumerator<>))] [assembly: TypeForwardedTo(typeof(IAsyncDisposable))] [assembly: TypeForwardedTo(typeof(AsyncIteratorMethodBuilder))] [assembly: TypeForwardedTo(typeof(AsyncIteratorStateMachineAttribute))] [assembly: TypeForwardedTo(typeof(ConfiguredAsyncDisposable))] [assembly: TypeForwardedTo(typeof(ConfiguredCancelableAsyncEnumerable<>))] [assembly: TypeForwardedTo(typeof(EnumeratorCancellationAttribute))] [assembly: TypeForwardedTo(typeof(ManualResetValueTaskSourceCore<>))] [assembly: TypeForwardedTo(typeof(TaskAsyncEnumerableExtensions))] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } } namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class LibraryImportAttribute : Attribute { public string LibraryName { get; } public string EntryPoint { get; set; } public StringMarshalling StringMarshalling { get; set; } public Type StringMarshallingCustomType { get; set; } public bool SetLastError { get; set; } public LibraryImportAttribute(string libraryName) { LibraryName = libraryName; } } internal enum StringMarshalling { Custom, Utf8, Utf16 } }