Compare commits
No commits in common. "199540e530d0605002524fb9981cbb74c4f137cd" and "2a0430b7ecaf658d37eab4bc16a61f0930a17413" have entirely different histories.
199540e530
...
2a0430b7ec
@ -1,5 +1,6 @@
|
||||
using System.Net;
|
||||
using ExcelDna.IntelliSense;
|
||||
using Microsoft.Office.Interop.Excel;
|
||||
#if !NET472
|
||||
using System.Runtime.Versioning;
|
||||
#endif
|
||||
|
@ -119,8 +119,8 @@ public class RibbonController : ExcelRibbon
|
||||
|
||||
else
|
||||
{
|
||||
Worksheet worksheet = RhSolutionsAddIn.Excel.ActiveWorkbook.ActiveSheet;
|
||||
_workbookIsValid = worksheet.IsValidSource();
|
||||
WorksheetValidator.Validate(RhSolutionsAddIn.Excel.ActiveSheet);
|
||||
_workbookIsValid = WorksheetValidator.IsValid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<DnaLibrary Name="RhSolutions Add-In" RuntimeVersion="v4.0" xmlns="http://schemas.excel-dna.net/addin/2020/07/dnalibrary">
|
||||
<ExternalLibrary Path="RhSolutions.AddIn.dll" ExplicitExports="false" LoadFromBytes="true" Pack="true" IncludePdb="false" />
|
||||
<Reference Path="ExcelDna.IntelliSense.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.AspNetCore.Http.Abstractions.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.AspNetCore.Http.Extensions.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.AspNetCore.Http.Features.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Bcl.AsyncInterfaces.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Bcl.HashCode.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.Caching.Abstractions.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.Caching.Memory.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.DependencyInjection.Abstractions.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.DependencyInjection.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.FileProviders.Abstractions.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.Http.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.Logging.Abstractions.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.Logging.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.Options.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Extensions.Primitives.dll" Pack="true" />
|
||||
<Reference Path="Microsoft.Net.Http.Headers.dll" Pack="true" />
|
||||
<Reference Path="netDxf.dll" Pack="true" />
|
||||
<Reference Path="ExcelDna.IntelliSense.dll" Pack="true" />
|
||||
<Reference Path="Newtonsoft.Json.dll" Pack="true" />
|
||||
<Reference Path="netDxf.dll" Pack="true" />
|
||||
<Reference Path="RhSolutions.ProductSku.dll" Pack="true" />
|
||||
<Reference Path="System.Buffers.dll" Pack="true" />
|
||||
<Reference Path="System.Diagnostics.DiagnosticSource.dll" Pack="true" />
|
||||
<Reference Path="System.Memory.dll" Pack="true" />
|
||||
<Reference Path="System.Numerics.Vectors.dll" Pack="true" />
|
||||
<Reference Path="System.Runtime.CompilerServices.Unsafe.dll" Pack="true" />
|
||||
<Reference Path="System.Text.Encodings.Web.dll" Pack="true" />
|
||||
<Reference Path="System.Threading.Tasks.Extensions.dll" Pack="true" />
|
||||
<Reference Path="System.ValueTuple.dll" Pack="true" />
|
||||
</DnaLibrary>
|
||||
|
@ -14,25 +14,24 @@
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net472|AnyCPU'">
|
||||
<NoWarn>1701;1702</NoWarn>
|
||||
<NoWarn>1701;1702</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net472|AnyCPU'">
|
||||
<NoWarn>1701;1702</NoWarn>
|
||||
<NoWarn>1701;1702</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-windows7.0|AnyCPU'">
|
||||
<NoWarn>1701;1702</NoWarn>
|
||||
<NoWarn>1701;1702</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-windows7.0|AnyCPU'">
|
||||
<NoWarn>1701;1702</NoWarn>
|
||||
<NoWarn>1701;1702</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ExcelDna.AddIn" Version="1.6.0">
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
<TreatAsUsed>true</TreatAsUsed>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ExcelDna.Integration" Version="1.6.0" />
|
||||
<PackageReference Include="ExcelDna.IntelliSense" Version="1.6.0" />
|
||||
<PackageReference Include="ExcelDna.Interop" Version="15.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
|
@ -1,10 +1,8 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Newtonsoft.Json;
|
||||
using System.Web;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
|
||||
namespace RhSolutions.Services;
|
||||
|
||||
@ -55,13 +53,9 @@ public class DatabaseClient : IDatabaseClient
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
QueryBuilder qb = new()
|
||||
{
|
||||
{"query", line}
|
||||
};
|
||||
string request = @"https://rh.cebotari.ru/api/search" + qb.ToQueryString();
|
||||
|
||||
{
|
||||
string request = @"https://rh.cebotari.ru/api/search?query=" + line;
|
||||
|
||||
if (!_memoryCache.TryGetValue(line, out IEnumerable<Product> products))
|
||||
{
|
||||
var response = await _httpClient.GetAsync(request);
|
||||
|
@ -85,7 +85,7 @@ public class ExcelReader : IReader, IDisposable
|
||||
List<(string, Dictionary<Product, double>)> result = new();
|
||||
foreach (Worksheet worksheet in worksheets)
|
||||
{
|
||||
if (!worksheet.IsValidSource())
|
||||
if (!WorksheetValidator.IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -93,12 +93,11 @@ public class ExcelReader : IReader, IDisposable
|
||||
string wbName = Path.GetFileNameWithoutExtension(
|
||||
worksheet.Parent.Name);
|
||||
|
||||
Range amountCell = worksheet.Cells.Find(headers["Amount"]);
|
||||
Range headerRow = amountCell.EntireRow;
|
||||
Range skuCell = headerRow.Find(headers["Sku"]),
|
||||
productLineCell = headerRow.Find(headers["ProductLine"]),
|
||||
nameCell = headerRow.Find(headers["Name"]),
|
||||
measureCell = headerRow.Find(headers["Measure"]);
|
||||
Range amountCell = WorksheetValidator.HeaderCells["Amount"],
|
||||
skuCell = WorksheetValidator.HeaderCells["Sku"],
|
||||
productLineCell = WorksheetValidator.HeaderCells["ProductLine"],
|
||||
nameCell = WorksheetValidator.HeaderCells["Name"],
|
||||
measureCell = WorksheetValidator.HeaderCells["Measure"];
|
||||
|
||||
var lastRowIndex = worksheet.Cells[worksheet.Rows.Count, skuCell.Column]
|
||||
.End[XlDirection.xlUp].Row;
|
||||
|
@ -31,7 +31,7 @@ namespace RhSolutions.Services
|
||||
|
||||
public void WriteProducts(IEnumerable<(string, Dictionary<Product, double>)> products)
|
||||
{
|
||||
if (!_worksheet.IsValidSource())
|
||||
if (!WorksheetValidator.IsValid())
|
||||
{
|
||||
_application.ActiveWorkbook.Close();
|
||||
throw new ArgumentException(
|
||||
@ -40,11 +40,11 @@ namespace RhSolutions.Services
|
||||
|
||||
ShowFilteredData();
|
||||
|
||||
_amountCell = _worksheet.Cells.Find(_headers["Amount"]);
|
||||
_skuCell = _worksheet.Cells.Find(_headers["Sku"]);
|
||||
_programLineCell = _worksheet.Cells.Find(_headers["ProductLine"]);
|
||||
_nameCell = _worksheet.Cells.Find(_headers["Name"]);
|
||||
_oldSkuCell = _worksheet.Cells.Find(_headers["OldSku"]);
|
||||
_amountCell = WorksheetValidator.HeaderCells["Amount"];
|
||||
_skuCell = WorksheetValidator.HeaderCells["Sku"];
|
||||
_programLineCell = WorksheetValidator.HeaderCells["ProductLine"];
|
||||
_nameCell = WorksheetValidator.HeaderCells["Name"];
|
||||
_oldSkuCell = WorksheetValidator.HeaderCells["OldSku"];
|
||||
|
||||
_progressBar = new("Заполняю строки...", products
|
||||
.Select(p => p.Item2)
|
||||
|
50
RhSolutions.AddIn/Services/WorksheetValidator.cs
Normal file
50
RhSolutions.AddIn/Services/WorksheetValidator.cs
Normal file
@ -0,0 +1,50 @@
|
||||
#if !NET472
|
||||
using System.Runtime.Versioning;
|
||||
#endif
|
||||
|
||||
namespace RhSolutions.Services;
|
||||
|
||||
public static class WorksheetValidator
|
||||
{
|
||||
public static Dictionary<string, Range> HeaderCells { get; private set; }
|
||||
|
||||
public static void Validate(this Worksheet worksheet)
|
||||
{
|
||||
Range headerRow = null;
|
||||
HeaderCells = new();
|
||||
var headers = RhSolutionsAddIn.Configuration.GetPriceListHeaders();
|
||||
|
||||
foreach (var kvp in headers)
|
||||
{
|
||||
Range cell;
|
||||
|
||||
if (headerRow == null)
|
||||
{
|
||||
cell = worksheet.Cells.Find(kvp.Value);
|
||||
if (cell == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
headerRow = cell.EntireRow;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell = headerRow.Cells.Find(kvp.Value);
|
||||
}
|
||||
|
||||
if (HeaderCells.ContainsKey(kvp.Key))
|
||||
{
|
||||
HeaderCells[kvp.Key] = cell;
|
||||
}
|
||||
else
|
||||
{
|
||||
HeaderCells.Add(kvp.Key, cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsValid()
|
||||
{
|
||||
return HeaderCells.Count >= RhSolutionsAddIn.Configuration.GetPriceListHeaders().Count - 1;
|
||||
}
|
||||
}
|
@ -9,39 +9,6 @@ namespace RhSolutions.Tools;
|
||||
#endif
|
||||
public static class WorksheetExtensions
|
||||
{
|
||||
private static readonly Dictionary<string, string> pricelistParameters =
|
||||
RhSolutionsAddIn.Configuration.GetPriceListHeaders();
|
||||
|
||||
public static bool IsValidSource(this Worksheet worksheet)
|
||||
{
|
||||
Range headerRow;
|
||||
|
||||
string[] fields = pricelistParameters.Values
|
||||
.Where(v => v != "Прежний материал")
|
||||
.ToArray();
|
||||
|
||||
var value = worksheet.Cells.Find(fields[0]);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
headerRow = value.EntireRow;
|
||||
}
|
||||
|
||||
for (int i = 1; i < fields.Length; i++)
|
||||
{
|
||||
if (headerRow.Find(fields[i]) == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void AddValue(this Range range, double value)
|
||||
{
|
||||
if (range.Value2 == null)
|
||||
|
@ -23,11 +23,13 @@ public class CanDoGuess : IDisposable
|
||||
public void CanWriteMultiplyRows()
|
||||
{
|
||||
Worksheet sourceSheet = Util.Workbook.Worksheets[1];
|
||||
sourceSheet.Validate();
|
||||
RhSolutionsAddIn.Configuration.SetPriceListPath(Path.GetFullPath(@"..\..\..\TestWorkbooks\TargetSpecificationGuess.xlsx"));
|
||||
var products = _guessReader.ReadProducts(new[] { sourceSheet });
|
||||
var _writer = new NewPriceWriter(Util.Application, RhSolutionsAddIn.Configuration);
|
||||
_writer.WriteProducts(products);
|
||||
Worksheet targetSheet = Util.Application.ActiveWindow.ActiveSheet;
|
||||
targetSheet.Validate();
|
||||
var targetProducts = _reader.ReadProducts(new[] { targetSheet });
|
||||
|
||||
Assert.Equal("TestSpecificationGuess", products.First().Item1);
|
||||
@ -40,11 +42,13 @@ public class CanDoGuess : IDisposable
|
||||
public void CanWriteOneRow()
|
||||
{
|
||||
Worksheet sourceSheet = Util.Workbook.Worksheets[1];
|
||||
sourceSheet.Validate();
|
||||
RhSolutionsAddIn.Configuration.SetPriceListPath(Path.GetFullPath(@"..\..\..\TestWorkbooks\TargetSpecificationGuessOneRow.xlsx"));
|
||||
var products = _guessReader.ReadProducts(new[] { sourceSheet });
|
||||
var _writer = new NewPriceWriter(Util.Application, RhSolutionsAddIn.Configuration);
|
||||
_writer.WriteProducts(products);
|
||||
Worksheet targetSheet = Util.Application.ActiveWindow.ActiveSheet;
|
||||
targetSheet.Validate();
|
||||
var targetProducts = _reader.ReadProducts(new[] { targetSheet });
|
||||
|
||||
Assert.Equal("TestSpecificationGuessOneRow", products.First().Item1);
|
||||
|
@ -24,6 +24,7 @@ public class CanFillSleeves : IDisposable
|
||||
[ExcelFact(Workbook = @"..\..\..\TestWorkbooks\TestSpecificationSleeves.xlsx")]
|
||||
public void CanCalculateSleeves()
|
||||
{
|
||||
_worksheet.Validate();
|
||||
var products = _reader.ReadProducts(new[] { _worksheet });
|
||||
var sleeves = _calculator.CalculateSleeves(products.First().Item2);
|
||||
_writer.WriteProducts(sleeves);
|
||||
|
@ -22,6 +22,7 @@ public class CanReadProducts : IDisposable
|
||||
public void CanReadRange()
|
||||
{
|
||||
Worksheet worksheet = _testWorkbook.Sheets[1];
|
||||
worksheet.Validate();
|
||||
worksheet.Range["A1"].Value = "11600011001";
|
||||
worksheet.Range["A2"].Value = "11600011001";
|
||||
worksheet.Range["A3"].Value = "160002-001";
|
||||
@ -49,6 +50,7 @@ public class CanReadProducts : IDisposable
|
||||
public void CanReadWorkbook()
|
||||
{
|
||||
Worksheet worksheet = Util.Workbook.Worksheets[1];
|
||||
worksheet.Validate();
|
||||
var result = _reader.ReadProducts(new[] { worksheet });
|
||||
Assert.NotNull(result);
|
||||
Assert.NotEmpty(result);
|
||||
|
@ -21,11 +21,13 @@ public class CanWriteProducts : IDisposable
|
||||
public void CanWriteSingle()
|
||||
{
|
||||
Worksheet sourceSheet = Util.Workbook.Worksheets[1];
|
||||
sourceSheet.Validate();
|
||||
RhSolutionsAddIn.Configuration.SetPriceListPath(Path.GetFullPath(@"..\..\..\TestWorkbooks\TargetSpecification.xlsx"));
|
||||
var products = _reader.ReadProducts(new[] { sourceSheet });
|
||||
var _writer = new NewPriceWriter(Util.Application, RhSolutionsAddIn.Configuration);
|
||||
_writer.WriteProducts(products);
|
||||
Worksheet targetSheet = Util.Application.ActiveWindow.ActiveSheet;
|
||||
targetSheet.Validate();
|
||||
var targetProducts = _reader.ReadProducts(new[] { targetSheet });
|
||||
|
||||
Assert.Equal("TestSpecification", products.First().Item1);
|
||||
@ -38,11 +40,13 @@ public class CanWriteProducts : IDisposable
|
||||
public void CanWriteMultipleProductLines()
|
||||
{
|
||||
Worksheet sourceSheet = Util.Workbook.Worksheets[1];
|
||||
sourceSheet.Validate();
|
||||
RhSolutionsAddIn.Configuration.SetPriceListPath(Path.GetFullPath(@"..\..\..\TestWorkbooks\TargetSpecificationMultipleProductLines.xlsx"));
|
||||
var products = _reader.ReadProducts(new[] { sourceSheet });
|
||||
var _writer = new NewPriceWriter(Util.Application, RhSolutionsAddIn.Configuration);
|
||||
_writer.WriteProducts(products);
|
||||
Worksheet targetSheet = Util.Application.ActiveWindow.ActiveSheet;
|
||||
targetSheet.Validate();
|
||||
var targetProducts = _reader.ReadProducts(new[] { targetSheet });
|
||||
|
||||
Assert.Equal("TestSpecificationMultipleProductLines", products.First().Item1);
|
||||
@ -55,11 +59,13 @@ public class CanWriteProducts : IDisposable
|
||||
public void CanWriteNotFound()
|
||||
{
|
||||
Worksheet sourceSheet = Util.Workbook.Worksheets[1];
|
||||
sourceSheet.Validate();
|
||||
RhSolutionsAddIn.Configuration.SetPriceListPath(Path.GetFullPath(@"..\..\..\TestWorkbooks\TargetSpecificationNotFound.xlsx"));
|
||||
var products = _reader.ReadProducts(new[] { sourceSheet });
|
||||
var _writer = new NewPriceWriter(Util.Application, RhSolutionsAddIn.Configuration);
|
||||
_writer.WriteProducts(products);
|
||||
Worksheet targetSheet = Util.Application.ActiveWindow.ActiveSheet;
|
||||
targetSheet.Validate();
|
||||
|
||||
Assert.Equal("???", targetSheet.Range["B4"].Value2);
|
||||
Assert.Contains("Молот Тора", targetSheet.Range["C4"].Value2);
|
||||
@ -70,11 +76,13 @@ public class CanWriteProducts : IDisposable
|
||||
public void CanWriteReplaced()
|
||||
{
|
||||
Worksheet sourceSheet = Util.Workbook.Worksheets[1];
|
||||
sourceSheet.Validate();
|
||||
RhSolutionsAddIn.Configuration.SetPriceListPath(Path.GetFullPath(@"..\..\..\TestWorkbooks\TargetSpecificationReplaced.xlsx"));
|
||||
var products = _reader.ReadProducts(new[] { sourceSheet });
|
||||
var _writer = new NewPriceWriter(Util.Application, RhSolutionsAddIn.Configuration);
|
||||
_writer.WriteProducts(products);
|
||||
Worksheet targetSheet = Util.Application.ActiveWindow.ActiveSheet;
|
||||
targetSheet.Validate();
|
||||
var targetProducts = _reader.ReadProducts(new[] { targetSheet });
|
||||
|
||||
Assert.Equal("TestSpecificationReplaced", products.First().Item1);
|
||||
@ -92,11 +100,13 @@ public class CanWriteProducts : IDisposable
|
||||
public void CanWriteNewVariant()
|
||||
{
|
||||
Worksheet sourceSheet = Util.Workbook.Worksheets[1];
|
||||
sourceSheet.Validate();
|
||||
RhSolutionsAddIn.Configuration.SetPriceListPath(Path.GetFullPath(@"..\..\..\TestWorkbooks\TargetSpecificationNewVariant.xlsx"));
|
||||
var products = _reader.ReadProducts(new[] { sourceSheet });
|
||||
var _writer = new NewPriceWriter(Util.Application, RhSolutionsAddIn.Configuration);
|
||||
_writer.WriteProducts(products);
|
||||
Worksheet targetSheet = Util.Application.ActiveWindow.ActiveSheet;
|
||||
targetSheet.Validate();
|
||||
var targetProducts = _reader.ReadProducts(new[] { targetSheet });
|
||||
|
||||
Assert.Equal("TestSpecificationNewVariant", products.First().Item1);
|
||||
|
@ -21,11 +21,13 @@ public class RealPricelistTest : IDisposable
|
||||
public void CanWrite()
|
||||
{
|
||||
Worksheet sourceSheet = Util.Workbook.Worksheets[1];
|
||||
sourceSheet.Validate();
|
||||
RhSolutionsAddIn.Configuration.SetPriceListPath(Path.GetFullPath(@"..\..\..\TestWorkbooks\RealTargetSpecification.xlsx"));
|
||||
var products = _reader.ReadProducts(new[] { sourceSheet });
|
||||
var _writer = new NewPriceWriter(Util.Application, RhSolutionsAddIn.Configuration);
|
||||
_writer.WriteProducts(products);
|
||||
Worksheet targetSheet = Util.Application.ActiveWindow.ActiveSheet;
|
||||
targetSheet.Validate();
|
||||
targetSheet.Range["A1"].Formula = "=SUM(H:H)";
|
||||
|
||||
Assert.Equal("RealTestSpecification", products.First().Item1);
|
||||
|
@ -1,5 +1,4 @@
|
||||
using RhSolutions.AddIn;
|
||||
using RhSolutions.Tools;
|
||||
|
||||
namespace RhSolutions.Tests;
|
||||
|
||||
@ -18,15 +17,17 @@ public class WorkbookValidationTests : IDisposable
|
||||
[ExcelFact(Workbook = @"..\..\..\TestWorkbooks\EmptyTestTable.xlsx")]
|
||||
public void WorksheetIsCorrect()
|
||||
{
|
||||
Worksheet worksheet = Util.Workbook.Sheets[1];
|
||||
Assert.True(worksheet.IsValidSource());
|
||||
Worksheet ws = Util.Workbook.Sheets[1];
|
||||
ws.Validate();
|
||||
Assert.True(WorksheetValidator.IsValid());
|
||||
}
|
||||
|
||||
[ExcelFact(Workbook = @"..\..\..\TestWorkbooks\EmptyWorkbook.xlsx")]
|
||||
public void EmptyWorkbookIsNotCorrect()
|
||||
{
|
||||
Worksheet worksheet = Util.Workbook.Sheets[1];
|
||||
Assert.False(worksheet.IsValidSource());
|
||||
Worksheet ws = Util.Workbook.Sheets[1];
|
||||
ws.Validate();
|
||||
Assert.False(WorksheetValidator.IsValid());
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
Loading…
Reference in New Issue
Block a user