Compare commits

..
10 Commits
Author SHA1 Message Date
saherelm f9c6671dd7 last ... 2026-08-01 10:53:09 +03:30
saherelm 14a5e49d11 cleanup Dependencies ... 2026-07-30 15:59:44 +03:30
saherelm 88050a3d13 last ... 2026-07-26 21:20:56 +03:30
saherelm 34b308c3c1 last ... 2026-06-12 23:50:45 +03:30
saherelm 7da6327aa6 Update Lang Version to 12 ... 2026-06-12 02:14:31 +03:30
saherelm 012a1b08f5 last ... 2026-05-30 00:41:12 +03:30
saherelm 06d7074622 add some new Extensions method for Class Manipulations using Reflection ... 2026-05-29 19:33:29 +03:30
saherelm f40f9eeac0 add supports for InvokeGeneric methods to return Types supports ... 2026-05-24 22:48:12 +03:30
saherelm 39452b51ff last ... 2026-05-22 20:26:06 +03:30
saherelm d8b5abeb93 Preparing Controllers ... 2026-05-16 01:15:03 +03:30
10 changed files with 565 additions and 28 deletions
+8
View File
@@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace xCommons.Configurations {
public partial class XSwaggerConfiguration {
public string Title { get; set; } = "";
@@ -7,6 +9,7 @@ namespace xCommons.Configurations {
public XSwaggerContact Contact { get; set; } = null;
public XSwaggerLicence License { get; set; } = null;
public Dictionary<string, string> DefaultValues {get; set;} = null;
}
public partial class XSwaggerContact {
@@ -19,4 +22,9 @@ namespace xCommons.Configurations {
public string Name { get; set; }
public string Url { get; set; }
}
public partial class XSwaggerDefaultValues
{
public Dictionary<string, string> Values { get; set; }
}
}
-4
View File
@@ -1,12 +1,8 @@
using System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using xCommons.Attributes;
using xCommons.Configurations;
using xCommons.Extensions;
using xCommons.Providers;
using xExceptions.Constants;
namespace xCommons.Controllers {
/// <summary>
+1 -1
View File
@@ -19,7 +19,7 @@ namespace xCommons.Controllers {
public XAppConfiguration AppConfiguration { get; }
public XValidationProvider ValidationProvider { get; }
public XBaseController (
protected XBaseController (
ILogger logger,
XAppConfiguration appConfiguration,
XValidationProvider validationProvider
+21 -4
View File
@@ -45,11 +45,13 @@ namespace xCommons.Extensions {
/// <param name="xmlFilePath"></param>
/// <param name="addRequiredXPoweredFilter"></param>
/// <param name="addXTokenAuthorization"></param>
/// <param name="addDefaultValueFilter"></param>
public static void AddXSwaggerGenOptions (
this SwaggerGenOptions source,
string xmlFilePath = null,
bool addRequiredXPoweredFilter = true,
bool addXTokenAuthorization = true
bool addXTokenAuthorization = true,
bool addDefaultValueFilter = true
) {
//
if (source.IsNull ()) {
@@ -68,6 +70,12 @@ namespace xCommons.Extensions {
source.OperationFilter<RequireXPoweredOperationFilter> ();
}
//
// Add Default Values Filter ...
if (addDefaultValueFilter) {
source.OperationFilter<SwaggerDefaultValuesOperationFilter> ();
}
//
// Handle XToken Authorizations ...
if (addXTokenAuthorization) {
@@ -151,13 +159,15 @@ namespace xCommons.Extensions {
/// <param name="xmlFilePath"></param>
/// <param name="addRequiredXPoweredFilter"></param>
/// <param name="addXTokenAuthorization"></param>
/// <param name="addDefaultValueFilter"></param>
public static void AddXSwagger (
this IServiceCollection source,
IConfiguration configuration,
SwaggerGenOptions settings = null,
string xmlFilePath = null,
bool addRequiredXPoweredFilter = true,
bool addXTokenAuthorization = true
bool addXTokenAuthorization = true,
bool addDefaultValueFilter = true
) {
//
var xSwaggerConfig = configuration.GetXSwaggerConfiguration ();
@@ -165,6 +175,9 @@ namespace xCommons.Extensions {
xSwaggerConfig = new XSwaggerConfiguration ();
}
//
source.AddSingleton(xSwaggerConfig);
//
#region Prepare SwaggerGenOptions ...
if (settings.IsNull ()) {
@@ -172,8 +185,9 @@ namespace xCommons.Extensions {
}
settings.AddXSwaggerGenOptions (
xmlFilePath: xmlFilePath,
addRequiredXPoweredFilter: addRequiredXPoweredFilter,
addXTokenAuthorization: addXTokenAuthorization
addDefaultValueFilter: addDefaultValueFilter,
addXTokenAuthorization: addXTokenAuthorization,
addRequiredXPoweredFilter: addRequiredXPoweredFilter
);
#endregion
@@ -242,6 +256,9 @@ namespace xCommons.Extensions {
opt.SwaggerDoc ("v1", apiDoc);
}
);
//
// Register Swagger Operation Filters ...
}
/// <summary>
+149
View File
@@ -0,0 +1,149 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using UglyToad.PdfPig;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using xCommons.Extensions;
namespace xAiModels.Extensions
{
public static class IFormFileExtensions
{
/// <summary>
/// Read a IFormFile Content as byte array ...
/// </summary>
/// <param name="source"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<byte[]> ReadAsBytes(
this IFormFile source,
CancellationToken cancellationToken = default
)
{
//
// Create and use a Memory Stream ...
using var stream = new MemoryStream();
//
// Copy File Content to Stream ...
await source.CopyToAsync(
target: stream,
cancellationToken: cancellationToken
);
//
// Read Stream Content as byte array ...
var result = stream.ToArray();
//
return result;
}
/// <summary>
/// Read a File Content by it's Path as byte array ...
/// </summary>
/// <param name="filePath"></param>
/// <param name="bufferSize"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static async Task<byte[]> ReadAsBytes(
this string filePath,
int bufferSize = 81920,
CancellationToken cancellationToken = default
)
{
//
if (string.IsNullOrWhiteSpace(filePath))
{
throw new Exception("Invalid Args ...");
}
//
// Create and use a Memory Stream ...
using var memStream = new MemoryStream();
//
using var stream = new FileStream(
path: filePath,
mode: FileMode.Open,
access: FileAccess.Read,
share: FileShare.ReadWrite
);
//
// Copy File Content to Stream ...
await stream.CopyToAsync(
destination: memStream,
bufferSize: bufferSize,
cancellationToken: cancellationToken
);
//
// Read Stream Content as byte array ...
var result = memStream.ToArray();
//
return result;
}
/// <summary>
/// Read Text Content of Document ...
/// </summary>
/// <param name="source"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<string> ReadContent(
this IFormFile source,
CancellationToken cancellationToken = default
)
{
//
// Check if File PDF or not ...
var isPDF = source.ContentType
.ToNormalString()
.Contains("pdf"
.ToNormalString());
//
var result = string.Empty;
//
var isValidFileType = isPDF;
if (!isValidFileType)
{
return result;
}
//
if (isPDF)
{
//
// Reading File Content as Byte array ...
var fileBytes = await source.ReadAsBytes(cancellationToken);
//
// Create a PDF Document ...
using var stream = new MemoryStream(fileBytes);
using var document = PdfDocument.Open(stream);
//
// Extract PDF Text ...
var textBuilder = new StringBuilder();
foreach (var page in document.GetPages())
{
textBuilder.Append(page.Text);
}
//
result = textBuilder.ToString();
}
//
return result;
}
}
}
+264 -8
View File
@@ -3,11 +3,22 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace xCommons.Extensions
{
public static partial class ModelExtensions
{
/// <summary>
/// Retrieve a Binding Flag for Retrieve all Instance Members including
/// Priate and Public ...
/// </summary>
/// <returns></returns>
public static BindingFlags GetDefaultBindingFlag()
{
return BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
}
/// <summary>
/// Update an Instance of a Typed Object with Data Provided by another Instance of Typed Object
/// </summary>
@@ -105,23 +116,167 @@ namespace xCommons.Extensions
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="property"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static bool HasProperty<T>(
this T source,
string property
string property,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
var result = source
.GetType()
.GetProperties()
.GetProperties(bindingAttr)
.Any(prop => prop.Name == property); ;
//
return result;
}
/// <summary>
/// Check a Class is Contains a field or not ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="field"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static bool HasField<T>(
this T source,
string field,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
var result = source
.GetType()
.GetFields(bindingAttr)
.Any(fld => fld.Name == field);
//
return result;
}
/// <summary>
/// Check a Class is Contains a Method or not ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="method"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static bool HasMethod<T>(
this T source,
string method,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
var result = source
.GetType()
.GetMethods(bindingAttr)
.Any(mthd => mthd.Name == method);
//
return result;
}
/// <summary>
/// Retrieve a Class Properties Names ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static string[] GetPropertiesNames<T>(
this T source,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
{
//
var result = source
.GetType()
.GetProperties(bindingAttr)
.Select(p => p.Name)
.ToArray();
//
return result;
}
/// <summary>
/// Retrieve a Class Fields Names ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static string[] GetFieldsNames<T>(
this T source,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
{
//
var result = source
.GetType()
.GetFields(bindingAttr)
.Select(p => p.Name)
.ToArray();
//
return result;
}
/// <summary>
/// Retrieve a Class Methods Names ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static string[] GetMethodsNames<T>(
this T source,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
{
//
var result = source
.GetType()
.GetMethods(bindingAttr)
.Select(p => p.Name)
.ToArray();
//
return result;
}
/// <summary>
/// Retrieve a Class Members Names ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static string[] GetMembersNames<T>(
this T source,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
{
//
var result = source
.GetType()
.GetMembers(bindingAttr)
.Select(p => p.Name)
.ToArray();
//
return result;
}
/// <summary>
/// Get a Class Property Value using Generic Concept ...
/// </summary>
@@ -129,15 +284,17 @@ namespace xCommons.Extensions
/// <typeparam name="TProp"></typeparam>
/// <param name="source"></param>
/// <param name="property"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static TProp GetProperty<T, TProp>(
this T source,
string property
string property,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
TProp result = default(TProp);
TProp result = default;
//
// Check if T Has Property ...
@@ -147,7 +304,10 @@ namespace xCommons.Extensions
// Access Property ...
var prop = source
.GetType()
.GetProperty(property);
.GetProperty(
property,
bindingAttr
);
//
// Retrieve Property Value as Object ...
@@ -162,18 +322,59 @@ namespace xCommons.Extensions
}
/// <summary>
/// Setting Property Value of T ...
/// Get a Class Field Value using Generic Concept ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TField"></typeparam>
/// <param name="source"></param>
/// <param name="field"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static TField GetField<T, TField>(
this T source,
string field,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
TField result = default;
//
if (source.HasField(field))
{
//
var fld = source
.GetType()
.GetField(
field,
bindingAttr
);
//
var fieldVal = fld.GetValue(source);
result = (TField)fieldVal;
}
//
return result;
}
/// <summary>
/// Set a Class Property Value using Generic Concept ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProp"></typeparam>
/// <param name="source"></param>
/// <param name="property"></param>
/// <param name="value"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static bool SetProperty<T, TProp>(
this T source,
string property,
TProp value
TProp value,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
@@ -189,7 +390,10 @@ namespace xCommons.Extensions
// Access Property ...
var prop = source
.GetType()
.GetProperty(property);
.GetProperty(
property,
bindingAttr
);
//
// Set Property ...
@@ -208,6 +412,58 @@ namespace xCommons.Extensions
return result;
}
/// <summary>
/// Set a Class Field Value using Generic Concept ...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TField"></typeparam>
/// <param name="source"></param>
/// <param name="field"></param>
/// <param name="value"></param>
/// <param name="bindingAttr"></param>
/// <returns></returns>
public static bool SetField<T, TField>(
this T source,
string field,
TField value,
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
)
where T : class
{
//
// Check T Has Field ...
var result = source.HasField(field);
if (!result)
{
return result;
}
//
// Access Field ...
var fld = source
.GetType()
.GetField(
field,
bindingAttr
);
//
// Set Value ...
try
{
//
result = true;
fld.SetValue(source, value);
}
catch
{
result = false;
}
//
return result;
}
/// <summary>
/// Check two Instance of Typed Object Values are Same or not
/// </summary>
@@ -0,0 +1,48 @@
using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using xCommons.Configurations;
using xCommons.Extensions;
namespace xCommons.Filters
{
public class SwaggerDefaultValuesOperationFilter : IOperationFilter
{
private readonly XSwaggerConfiguration config;
public SwaggerDefaultValuesOperationFilter(
XSwaggerConfiguration config
)
{
this.config = config;
}
public void Apply(
OpenApiOperation operation,
OperationFilterContext context
)
{
//
// Validate Configuration ...
if (
!config.IsNull() &&
!config.DefaultValues.IsNull() &&
config.DefaultValues.HasChild()
)
{
//
foreach (var prv in config.DefaultValues)
{
//
// Detect Parameter ...
var swaggerParam = operation.Parameters.FirstOrDefault(p => p.Name == prv.Key);
if (!swaggerParam.IsNull())
{
swaggerParam.Schema.Default = new OpenApiString(prv.Value);
}
}
}
}
}
}
+60 -4
View File
@@ -21,6 +21,30 @@ namespace xCommons.Helpers
Type runtimeType,
params object[] args
)
{
//
source.InvokeGenericMethod<object>(
args: args,
methodName: methodName,
runtimeType: runtimeType
);
}
/// <summary>
/// Invoke a Generic Method of Specified Type ...
/// </summary>
/// <typeparam name="TResponse"></typeparam>
/// <param name="source"></param>
/// <param name="methodName"></param>
/// <param name="runtimeType"></param>
/// <param name="args"></param>
/// <returns></returns>
public static TResponse InvokeGenericMethod<TResponse>(
this Type source,
string methodName,
Type runtimeType,
params object[] args
)
{
//
var overLoads = source.GetGenericMethodInfo(
@@ -28,7 +52,7 @@ namespace xCommons.Helpers
);
if (!overLoads.HasChild())
{
return;
return default;
}
//
@@ -36,7 +60,11 @@ namespace xCommons.Helpers
MethodInfo genericMethod = method.MakeGenericMethod(runtimeType);
//
genericMethod.Invoke(null, args);
var resultObj = genericMethod.Invoke(null, args);
var result = (TResponse)resultObj;
//
return result;
}
/// <summary>
@@ -52,6 +80,30 @@ namespace xCommons.Helpers
Type[] runtimeTypes,
params object[] args
)
{
//
source.InvokeGenericMethod<object>(
args: args,
methodName: methodName,
runtimeTypes: runtimeTypes
);
}
/// <summary>
/// Invoke a Generic Method of Specified Type ...
/// </summary>
/// <typeparam name="TResponse"></typeparam>
/// <param name="source"></param>
/// <param name="methodName"></param>
/// <param name="runtimeTypes"></param>
/// <param name="args"></param>
/// <returns></returns>
public static TResponse InvokeGenericMethod<TResponse>(
this Type source,
string methodName,
Type[] runtimeTypes,
params object[] args
)
{
//
var overLoads = source.GetGenericMethodInfo(
@@ -59,7 +111,7 @@ namespace xCommons.Helpers
);
if (!overLoads.HasChild())
{
return;
return default;
}
//
@@ -69,7 +121,11 @@ namespace xCommons.Helpers
MethodInfo genericMethod = method.MakeGenericMethod(runtimeTypes);
//
genericMethod.Invoke(null, args);
var resultObj = genericMethod.Invoke(null, args);
var result = resultObj.ConvertTo<TResponse>();
//
return result;
}
/// <summary>
+2 -1
View File
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!-- <add key="megan" value="https://hub.megan.ir/nuget/index.json" /> -->
<add key="nuget" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="liget" value="https://nuget.saherelmhub.ir/v3/index.json" protocolVersion="3" />
<add key="baget" value="https://nuget.saherelmhub.ir/v3/index.json" protocolVersion="3" disableTLSCertificateValidation="true" />
</packageSources>
</configuration>
+11 -5
View File
@@ -1,14 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Runtime Definition -->
<PropertyGroup>
<Version>1.0.0</Version>
<LangVersion>8.0</LangVersion>
<LangVersion>12.0</LangVersion>
<Authors>Hadi Khazaee Asl</Authors>
<Company>SaherElm IT Center</Company>
<PackageId>xDashboard.xCommons</PackageId>
<TargetFramework>netstandard2.0</TargetFramework>
<Description>
provide all commonly used actions/extensions and classes which required to xDashboard project.
provide all commonly used actions/extensions and classes which required to xDashboard project.
</Description>
<!-- Icon Definition -->
@@ -17,17 +19,18 @@
<!-- Icon Handling -->
<ItemGroup>
<None Include="../../Resources/Images/favicon.png" Link="icon.png" Pack="true" PackagePath="\icon.png" />
<None Include="../../Resources/Images/favicon.png" Link="icon.png" Pack="true"
PackagePath="\icon.png" />
</ItemGroup>
<!-- Local Modules -->
<ItemGroup>
<PackageReference Include="xDashboard.xExceptions" Version="1.0.0" />
<!-- <PackageReference Include="xDashboard.xExceptions" Version="1.0.0" /> -->
</ItemGroup>
<!-- Local Dependencies -->
<ItemGroup>
<!-- <ProjectReference Include="../xExceptions/xExceptions.csproj" /> -->
<ProjectReference Include="../xExceptions/xExceptions.csproj" />
</ItemGroup>
<!-- Dependencies -->
@@ -37,6 +40,8 @@
<PackageReference Include="System.Reactive" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="libphonenumber-csharp" Version="8.12.17" />
<PackageReference Include="UglyToad.PdfPig" Version="1.7.0-custom-5" />
<PackageReference Include="Spire.PDFfor.NETStandard" Version="12.5.8" />
<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
@@ -64,4 +69,5 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
</Project>