initial
This commit is contained in:
+407
@@ -0,0 +1,407 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*.props
|
||||||
|
*.db
|
||||||
|
*.db-shm
|
||||||
|
*.db-wal
|
||||||
|
|
||||||
|
AsilCore/[Oo]bj/
|
||||||
|
AsilCore/[Oo]bj/
|
||||||
|
AsilCore/[Oo]bj/
|
||||||
|
BlazorWasm/[Oo]bj/
|
||||||
|
SubAsil.Api/[Oo]bj/
|
||||||
|
SubAsil.ConsoleApp/[Oo]bj/
|
||||||
|
SubAsil.Core/[Oo]bj/
|
||||||
|
SubAsil.DataLayer/[Oo]bj/
|
||||||
|
SubAsil.Models/[Oo]bj/
|
||||||
|
TelBot_Music.Console/[Oo]bj/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AsilCore/obj/
|
||||||
|
AsilCore/obj/
|
||||||
|
AsilCore/obj/
|
||||||
|
BlazorWasm/obj/
|
||||||
|
SubAsil.Api/obj/
|
||||||
|
SubAsil.ConsoleApp/obj/
|
||||||
|
SubAsil.Core/obj/
|
||||||
|
SubAsil.DataLayer/obj/
|
||||||
|
SubAsil.Models/obj/
|
||||||
|
TelBot_Music.Console/obj/
|
||||||
|
/SubAsil.Api/appsettings.json
|
||||||
|
|
||||||
|
/SubAsil.Api/appsettings.json
|
||||||
|
/SubAsil.Api/appsettings.json
|
||||||
|
.vscode
|
||||||
|
/SubAsil.Api/internal-nlog.txt
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
**/obj
|
||||||
|
**/bin
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Mf.Core.Interfaces
|
||||||
|
{
|
||||||
|
public interface ICommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ICreateCommand<TEntity>: ICommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IUpdateCommand<TEntity> : ICommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IDeleteCommand<TEntity> : ICommand
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Mf.Core.SubEntities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.Core.Interfaces
|
||||||
|
{
|
||||||
|
public interface IContextCore
|
||||||
|
{
|
||||||
|
public IGenericService<TEntity> GetService<TEntity>() where TEntity : class, IEntity;
|
||||||
|
|
||||||
|
public object GetService(Type type);
|
||||||
|
|
||||||
|
public void Dispose();
|
||||||
|
|
||||||
|
public void Migrate();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Mf.Core.Interfaces
|
||||||
|
{
|
||||||
|
public interface IEmailSender
|
||||||
|
{
|
||||||
|
string SendEmail(string subject, string address, string body);
|
||||||
|
string SendDataBaseEmail(string subject, string address, string body, string filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EmailConfig
|
||||||
|
{
|
||||||
|
public string FromAddress { get; set; }
|
||||||
|
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
public int Port { get; set; }
|
||||||
|
|
||||||
|
public string SmtAddress { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Mf.Core.SubEntities;
|
||||||
|
using Mf.Core.SubEntities.QueryModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.Core.Interfaces
|
||||||
|
{
|
||||||
|
public interface IGenericService<out TEntity> where TEntity : class, IEntity
|
||||||
|
{
|
||||||
|
public IEnumerable<TEntity> GetAll();
|
||||||
|
|
||||||
|
public IEnumerable<TEntity> GetList(QueryRequest? query = null);
|
||||||
|
|
||||||
|
#region Async MotimatDatabaseCore
|
||||||
|
public Task<IEntity> GetByIdAsync(CancellationToken cancellationToken, params object[] ids);
|
||||||
|
|
||||||
|
public Task<IEnumerable<IEntity>> AddRangeAsync(IEnumerable<IEntity> entities, CancellationToken cancellationToken, bool saveNow = true);
|
||||||
|
public Task<IEntity> UpdateAsync(object entity, CancellationToken cancellationToken, bool saveNow = true);
|
||||||
|
|
||||||
|
|
||||||
|
public Task<IEntity> DeleteAsync(object entity, CancellationToken cancellationToken, bool saveNow = true);
|
||||||
|
|
||||||
|
public Task<IEntity> AddAsync(object entity, CancellationToken cancellationToken, bool saveNow = true);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
|
||||||
|
namespace Mf.Core.OperationSystem
|
||||||
|
{
|
||||||
|
public static class OperationSystemService
|
||||||
|
{
|
||||||
|
public static OperationSystemType OS
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
PlatformID platform = Environment.OSVersion.Platform;
|
||||||
|
|
||||||
|
// Check if the operating system is Windows
|
||||||
|
if (platform == PlatformID.Win32NT || platform == PlatformID.Win32Windows)
|
||||||
|
{
|
||||||
|
Version version = Environment.OSVersion.Version;
|
||||||
|
return OperationSystemType.Windows;
|
||||||
|
// Retrieve and display the Windows version
|
||||||
|
}
|
||||||
|
else if (platform == PlatformID.Unix)
|
||||||
|
{
|
||||||
|
// Retrieve and display the Linux/Unix version
|
||||||
|
//string versionInfo = ExecuteCommand("uname -a");
|
||||||
|
//Console.WriteLine($"Version: {versionInfo}");
|
||||||
|
return OperationSystemType.Linux;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return OperationSystemType.Unknown;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string OperationSystemVersion
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return System.Runtime.InteropServices.RuntimeInformation.OSDescription;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OperationSystemType
|
||||||
|
{
|
||||||
|
Windows,
|
||||||
|
Linux,
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.Core.Services
|
||||||
|
{
|
||||||
|
public static class DateService
|
||||||
|
{
|
||||||
|
public static DateTime GetStartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
|
||||||
|
{
|
||||||
|
int diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
|
||||||
|
return dt.AddDays(-1 * diff).Date;
|
||||||
|
}
|
||||||
|
public static string ToShamsi(this DateTime DateTime1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PersianCalendar PersianCalendar1 = new PersianCalendar();
|
||||||
|
return string.Format(@"{0}/{1}/{2} {3}:{4}:{5}",
|
||||||
|
PersianCalendar1.GetYear(DateTime1),
|
||||||
|
PersianCalendar1.GetMonth(DateTime1).ToString("00"),
|
||||||
|
PersianCalendar1.GetDayOfMonth(DateTime1).ToString("00"),
|
||||||
|
PersianCalendar1.GetHour(DateTime1).ToString("00"),
|
||||||
|
PersianCalendar1.GetMinute(DateTime1).ToString("00"),
|
||||||
|
PersianCalendar1.GetSecond(DateTime1).ToString("00")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToShamsiDate(this DateTime DateTime1)
|
||||||
|
{
|
||||||
|
PersianCalendar PersianCalendar1 = new PersianCalendar();
|
||||||
|
return string.Format(@"{0}/{1}/{2}",
|
||||||
|
PersianCalendar1.GetYear(DateTime1),
|
||||||
|
PersianCalendar1.GetMonth(DateTime1).ToString("00"),
|
||||||
|
PersianCalendar1.GetDayOfMonth(DateTime1).ToString("00"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToShamsiClock(this DateTime dateTime)
|
||||||
|
{
|
||||||
|
PersianCalendar PersianCalendar1 = new PersianCalendar();
|
||||||
|
return string.Format(@"{0}:{1}",
|
||||||
|
PersianCalendar1.GetHour(dateTime).ToString("00"),
|
||||||
|
PersianCalendar1.GetMinute(dateTime).ToString("00"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DateTime StringToDateTime(this string value)
|
||||||
|
{
|
||||||
|
string[] dateTmp = value.Split(' ');
|
||||||
|
string[] date = dateTmp[0].Split('/');
|
||||||
|
string[] time;
|
||||||
|
if (dateTmp.Length == 2)
|
||||||
|
{
|
||||||
|
time = dateTmp[1].Split(':');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
time = new string[2] { "0", "0" };
|
||||||
|
//date = value.Split('/');
|
||||||
|
PersianCalendar persianCal = new PersianCalendar();
|
||||||
|
return persianCal.ToDateTime(Convert.ToInt16(date[0]), Convert.ToInt16(date[1]), Convert.ToInt16(date[2]), int.Parse(time[0]), int.Parse(time[1]), int.Parse(time[2]), 0);
|
||||||
|
|
||||||
|
return new DateTime(Convert.ToInt16(date[0]), Convert.ToInt16(date[1]), Convert.ToInt16(date[2]));
|
||||||
|
// return new JalaliDate(Convert.ToInt16(date[0]), Convert.ToByte(date[1]), Convert.ToByte(date[2])).ToDateTime().AddHours(double.Parse(time[0])).AddMinutes(double.Parse(time[1]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static DateTime StringDateToDateTime(this string value)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
string[] dateTmp = value.Split(' ');
|
||||||
|
string[] date = dateTmp[0].Split('/');
|
||||||
|
string[] time;
|
||||||
|
if (dateTmp.Length == 2)
|
||||||
|
{
|
||||||
|
time = dateTmp[1].Split(':');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
time = new string[2] { "0", "0" };
|
||||||
|
//date = value.Split('/');
|
||||||
|
PersianCalendar persianCal = new PersianCalendar();
|
||||||
|
return persianCal.ToDateTime(Convert.ToInt16(date[0]), Convert.ToInt16(date[1]), Convert.ToInt16(date[2]), int.Parse(time[0]), int.Parse(time[1]), 0, 0);
|
||||||
|
|
||||||
|
return new DateTime(Convert.ToInt16(date[0]), Convert.ToInt16(date[1]), Convert.ToInt16(date[2]));
|
||||||
|
// return new JalaliDate(Convert.ToInt16(date[0]), Convert.ToByte(date[1]), Convert.ToByte(date[2])).ToDateTime().AddHours(double.Parse(time[0])).AddMinutes(double.Parse(time[1]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static TimeSpan StringToTimeSpan(this string value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var split = value.Split(":");
|
||||||
|
return new TimeSpan(int.Parse(split[0]), int.Parse(split[1]), int.Parse(split[2]));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//Console.WriteLine(ex);
|
||||||
|
return new TimeSpan();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DayOfWeekShamsi(this DayOfWeek day)
|
||||||
|
{
|
||||||
|
switch (day)
|
||||||
|
{
|
||||||
|
case (DayOfWeek.Saturday):
|
||||||
|
return "شنبه";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (DayOfWeek.Sunday):
|
||||||
|
return "یک شنبه";
|
||||||
|
break;
|
||||||
|
case (DayOfWeek.Monday):
|
||||||
|
return "دو شنبه";
|
||||||
|
case (DayOfWeek.Tuesday):
|
||||||
|
return "سه شنبه";
|
||||||
|
case (DayOfWeek.Wednesday):
|
||||||
|
return "چهار شنبه";
|
||||||
|
case (DayOfWeek.Thursday):
|
||||||
|
return "پنج شنبه";
|
||||||
|
case (DayOfWeek.Friday):
|
||||||
|
return "جمعه";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//public static class DateConvertor
|
||||||
|
//{
|
||||||
|
// public static string ToShamsi(this DateTime date)
|
||||||
|
// {
|
||||||
|
// PersianCalendar persian = new PersianCalendar();
|
||||||
|
// return persian.GetYear(date) + "/" + persian.GetMonth(date).ToString("00") + "/" + persian.GetDayOfMonth(date).ToString("00");
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
using Mf.Core.Interfaces;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Mail;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Mf.Core.Services
|
||||||
|
{
|
||||||
|
public class EmailSender : IEmailSender
|
||||||
|
{
|
||||||
|
public EmailConfig _config;
|
||||||
|
public EmailSender(EmailConfig config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SendEmail(string subject, string address, string body)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
|
||||||
|
client.EnableSsl = true;
|
||||||
|
client.Credentials = new NetworkCredential(_config.FromAddress, _config.Password);
|
||||||
|
MailAddress from = new MailAddress(_config.FromAddress);
|
||||||
|
MailAddress to = new MailAddress(address);
|
||||||
|
MailMessage message = new MailMessage(from, to);
|
||||||
|
message.Body = body;
|
||||||
|
message.BodyEncoding = Encoding.UTF8;
|
||||||
|
message.Subject = subject;
|
||||||
|
message.SubjectEncoding = Encoding.UTF8;
|
||||||
|
client.Send(message);
|
||||||
|
message.Dispose();
|
||||||
|
return "Success";
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ex.Message.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SendDataBaseEmail(string subject, string address, string body, string filePath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
|
||||||
|
client.EnableSsl = true;
|
||||||
|
client.Credentials = new NetworkCredential(_config.FromAddress, _config.Password);
|
||||||
|
MailAddress from = new MailAddress(_config.FromAddress);
|
||||||
|
MailAddress to = new MailAddress(address);
|
||||||
|
MailMessage message = new MailMessage(from, to);
|
||||||
|
message.Body = body;
|
||||||
|
message.BodyEncoding = Encoding.UTF8;
|
||||||
|
message.Subject = subject;
|
||||||
|
message.SubjectEncoding = Encoding.UTF8;
|
||||||
|
if (File.Exists(filePath))
|
||||||
|
{
|
||||||
|
Attachment attachment = new Attachment(filePath);
|
||||||
|
message.Attachments.Add(attachment);
|
||||||
|
}
|
||||||
|
client.Send(message);
|
||||||
|
message.Dispose();
|
||||||
|
return "Success";
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ex.Message.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.Core.SubEntities
|
||||||
|
{
|
||||||
|
public abstract class BaseEntity<T> : IEntity
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
[Display(Name = "شماره")]
|
||||||
|
|
||||||
|
public T Id { get; set; }
|
||||||
|
}
|
||||||
|
public abstract class BaseEntity : BaseEntity<long>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BaseEntityService
|
||||||
|
{
|
||||||
|
public static IEnumerable<Type> GetModelsByAttribute(Type attribute)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||||
|
|
||||||
|
// همهی تایپهای موجود در Assembly را دریافت میکنیم
|
||||||
|
Type[] types = assembly.GetTypes();
|
||||||
|
|
||||||
|
// لیستی برای نگهداری تایپهایی که دارای Custom Attribute مورد نظر هستند
|
||||||
|
List<Type> typesWithCustomAttribute = new List<Type>();
|
||||||
|
|
||||||
|
|
||||||
|
var typess = from assemblyy in AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
from type in assemblyy.GetTypes()
|
||||||
|
where type.IsDefined(attribute)
|
||||||
|
select type;
|
||||||
|
|
||||||
|
|
||||||
|
// بررسی Custom Attribute هر تایپ
|
||||||
|
foreach (Type type in typess)
|
||||||
|
{
|
||||||
|
// بررسی Custom Attribute هر تایپ
|
||||||
|
var attributes = type.GetCustomAttributes(attribute, false);
|
||||||
|
if (attributes.Length > 0)
|
||||||
|
{
|
||||||
|
// این تایپ دارای Custom Attribute مورد نظر است
|
||||||
|
typesWithCustomAttribute.Add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// چاپ نتیجهی تایپهای دارای Custom Attribute مورد نظر
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
//var types = from assembly in AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
// from type in assembly.GetTypes()
|
||||||
|
// where type.IsDefined(typeof(TableAttribute))
|
||||||
|
// select type;
|
||||||
|
return typesWithCustomAttribute;
|
||||||
|
|
||||||
|
|
||||||
|
var ass = typeof(BaseEntity).Assembly;
|
||||||
|
var all = ass.GetExportedTypes().Where(c => typeof(BaseEntity).IsAssignableFrom(c));
|
||||||
|
var aa = ass.GetExportedTypes().Where(c => c.IsClass && c.IsPublic && !c.IsAbstract && typeof(BaseEntity).IsAssignableFrom(c));
|
||||||
|
return aa;
|
||||||
|
|
||||||
|
// Assembly فعلی را دریافت میکنیم
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.Core.SubEntities
|
||||||
|
{
|
||||||
|
public interface IEntity
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Mf.Core.SubEntities.QueryModel
|
||||||
|
{
|
||||||
|
public class Filter
|
||||||
|
{
|
||||||
|
public string Field { get; set; }
|
||||||
|
public string Operator { get; set; }
|
||||||
|
public string Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
namespace Mf.Core.SubEntities.QueryModel
|
||||||
|
{
|
||||||
|
public class QueryRequest
|
||||||
|
{
|
||||||
|
public string? ObjectType { get; set; }
|
||||||
|
public List<Filter> Filters { get; set; } = new();
|
||||||
|
public List<string> Includes { get; set; } = new();
|
||||||
|
public int? Skip { get; set; }
|
||||||
|
public int? Take { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AlterRequest
|
||||||
|
{
|
||||||
|
public string? ObjectType { get; set; }
|
||||||
|
|
||||||
|
public object? Model { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Mf.Core\Mf.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,326 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Mf.Core.Interfaces;
|
||||||
|
using Mf.Core.SubEntities;
|
||||||
|
using Mf.Core.SubEntities.QueryModel;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.EfCore.Services
|
||||||
|
{
|
||||||
|
public class EntityFrameworkCoreServices<TEntity> : IGenericService<TEntity>, IDisposable
|
||||||
|
where TEntity : class, IEntity
|
||||||
|
{
|
||||||
|
protected readonly DbContext DbContext;
|
||||||
|
public DbSet<TEntity> Entities { get; }
|
||||||
|
public virtual IQueryable<TEntity> Table => Entities;
|
||||||
|
public virtual IQueryable<TEntity> TableNoTracking => Entities.AsNoTracking();
|
||||||
|
|
||||||
|
|
||||||
|
public EntityFrameworkCoreServices(DbContext dbContext)
|
||||||
|
{
|
||||||
|
DbContext = dbContext;
|
||||||
|
Entities = DbContext.Set<TEntity>(); // City => Cities
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Async Method
|
||||||
|
public virtual async Task<TEntity> GetByIdAsync(CancellationToken cancellationToken, params object[] ids)
|
||||||
|
{
|
||||||
|
return await Entities.FindAsync(ids, cancellationToken).AsTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task<TEntity> AddAsync(TEntity entity, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
var entityFull = await DbContext.AddAsync(entity, cancellationToken).ConfigureAwait(false);
|
||||||
|
if (saveNow)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
entityFull.State = EntityState.Detached;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entityFull.Entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task<IEnumerable<TEntity>> AddRangeAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
await Entities.AddRangeAsync(entities, cancellationToken).ConfigureAwait(false);
|
||||||
|
if (saveNow)
|
||||||
|
await DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task<TEntity> UpdateAsync(TEntity entity, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
var EntityState = Entities.Update(entity);
|
||||||
|
if (saveNow)
|
||||||
|
{
|
||||||
|
await DbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
EntityState.State = Microsoft.EntityFrameworkCore.EntityState.Detached;
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task<IEnumerable<TEntity>> UpdateRangeAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
Entities.UpdateRange(entities);
|
||||||
|
if (saveNow)
|
||||||
|
await DbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task<TEntity> DeleteAsync(TEntity entity, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Entities.Remove(entity);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
if (saveNow)
|
||||||
|
await DbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task<IEnumerable<TEntity>> DeleteRangeAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
Entities.RemoveRange(entities);
|
||||||
|
if (saveNow)
|
||||||
|
await DbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Sync Methods
|
||||||
|
public virtual TEntity GetById(params object[] ids)
|
||||||
|
{
|
||||||
|
return Entities.Find(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Add(TEntity entity, bool saveNow = true)
|
||||||
|
{
|
||||||
|
|
||||||
|
Entities.Add(entity);
|
||||||
|
if (saveNow)
|
||||||
|
DbContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void AddRange(IEnumerable<TEntity> entities, bool saveNow = true)
|
||||||
|
{
|
||||||
|
|
||||||
|
Entities.AddRange(entities);
|
||||||
|
if (saveNow)
|
||||||
|
DbContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update(TEntity entity, bool saveNow = true)
|
||||||
|
{
|
||||||
|
|
||||||
|
Entities.Update(entity);
|
||||||
|
DbContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void UpdateRange(IEnumerable<TEntity> entities, bool saveNow = true)
|
||||||
|
{
|
||||||
|
|
||||||
|
Entities.UpdateRange(entities);
|
||||||
|
if (saveNow)
|
||||||
|
DbContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Delete(TEntity entity, bool saveNow = true)
|
||||||
|
{
|
||||||
|
|
||||||
|
Entities.Remove(entity);
|
||||||
|
if (saveNow)
|
||||||
|
DbContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void DeleteRange(IEnumerable<TEntity> entities, bool saveNow = true)
|
||||||
|
{
|
||||||
|
|
||||||
|
Entities.RemoveRange(entities);
|
||||||
|
if (saveNow)
|
||||||
|
DbContext.SaveChanges();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Attach & Detach
|
||||||
|
public virtual void Detach(TEntity entity)
|
||||||
|
{
|
||||||
|
|
||||||
|
var entry = DbContext.Entry(entity);
|
||||||
|
if (entry != null)
|
||||||
|
entry.State = EntityState.Detached;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Attach(TEntity entity)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (DbContext.Entry(entity).State == EntityState.Detached)
|
||||||
|
Entities.Attach(entity);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Explicit Loading
|
||||||
|
public virtual async Task LoadCollectionAsync<TProperty>(TEntity entity, Expression<Func<TEntity, IEnumerable<TProperty>>> collectionProperty, CancellationToken cancellationToken)
|
||||||
|
where TProperty : class
|
||||||
|
{
|
||||||
|
Attach(entity);
|
||||||
|
|
||||||
|
var collection = DbContext.Entry(entity).Collection(collectionProperty);
|
||||||
|
if (!collection.IsLoaded)
|
||||||
|
await collection.LoadAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void LoadCollection<TProperty>(TEntity entity, Expression<Func<TEntity, IEnumerable<TProperty>>> collectionProperty)
|
||||||
|
where TProperty : class
|
||||||
|
{
|
||||||
|
Attach(entity);
|
||||||
|
var collection = DbContext.Entry(entity).Collection(collectionProperty);
|
||||||
|
if (!collection.IsLoaded)
|
||||||
|
collection.Load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task LoadReferenceAsync<TProperty>(TEntity entity, Expression<Func<TEntity, TProperty>> referenceProperty, CancellationToken cancellationToken)
|
||||||
|
where TProperty : class
|
||||||
|
{
|
||||||
|
Attach(entity);
|
||||||
|
var reference = DbContext.Entry(entity).Reference(referenceProperty);
|
||||||
|
if (!reference.IsLoaded)
|
||||||
|
await reference.LoadAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void LoadReference<TProperty>(TEntity entity, Expression<Func<TEntity, TProperty>> referenceProperty)
|
||||||
|
where TProperty : class
|
||||||
|
{
|
||||||
|
Attach(entity);
|
||||||
|
var reference = DbContext.Entry(entity).Reference(referenceProperty);
|
||||||
|
if (!reference.IsLoaded)
|
||||||
|
reference.Load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveChange()
|
||||||
|
{
|
||||||
|
DbContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> SaveChangeAsync()
|
||||||
|
{
|
||||||
|
await DbContext.SaveChangesAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
DbContext.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: Complte there
|
||||||
|
public IEnumerable<TEntity> GetAll()
|
||||||
|
{
|
||||||
|
return TableNoTracking;
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<IEntity> IGenericService<TEntity>.GetByIdAsync(CancellationToken cancellationToken, params object[] ids)
|
||||||
|
{
|
||||||
|
var res = await GetByIdAsync(cancellationToken, ids);
|
||||||
|
return (IEntity)res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<IEntity>> AddRangeAsync(IEnumerable<IEntity> entities, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEntity> UpdateAsync(object entity, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
var en = (TEntity)entity;
|
||||||
|
var result = await UpdateAsync(en, cancellationToken, saveNow);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEntity> AddAsync(object entity, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
var b = (TEntity)entity;
|
||||||
|
var res = await AddAsync(b, cancellationToken, saveNow);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEntity> DeleteAsync(object entity, CancellationToken cancellationToken, bool saveNow = true)
|
||||||
|
{
|
||||||
|
var en = (TEntity)entity;
|
||||||
|
var result = await DeleteAsync(en, cancellationToken, saveNow);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<TEntity> GetList(QueryRequest? query = null)
|
||||||
|
{
|
||||||
|
var products = TableNoTracking.AsQueryable();
|
||||||
|
if (query == null)
|
||||||
|
{
|
||||||
|
return products;
|
||||||
|
}
|
||||||
|
foreach (var include in query.Includes)
|
||||||
|
{
|
||||||
|
products = products.Include(include);
|
||||||
|
}
|
||||||
|
// 2. Apply Filters
|
||||||
|
foreach (var filter in query.Filters)
|
||||||
|
{
|
||||||
|
products = ApplyFilter(products, filter);
|
||||||
|
}
|
||||||
|
// 3. Apply Skip and Take
|
||||||
|
if (query.Skip.HasValue)
|
||||||
|
products = products.Skip(query.Skip.Value);
|
||||||
|
if (query.Take.HasValue)
|
||||||
|
products = products.Take(query.Take.Value);
|
||||||
|
return products;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQueryable<TEntity> ApplyFilter(IQueryable<TEntity> query, Filter filter)
|
||||||
|
{
|
||||||
|
var parameter = Expression.Parameter(typeof(TEntity), "x");
|
||||||
|
var property = Expression.Property(parameter, filter.Field);
|
||||||
|
var constant = Expression.Constant(Convert.ChangeType(filter.Value, property.Type));
|
||||||
|
|
||||||
|
Expression body = filter.Operator switch
|
||||||
|
{
|
||||||
|
"=" => Expression.Equal(property, constant),
|
||||||
|
">" => Expression.GreaterThan(property, constant),
|
||||||
|
">=" => Expression.GreaterThanOrEqual(property, constant),
|
||||||
|
"<" => Expression.LessThan(property, constant),
|
||||||
|
"<=" => Expression.LessThanOrEqual(property, constant),
|
||||||
|
"!=" => Expression.NotEqual(property, constant),
|
||||||
|
"Contains" => Expression.Call(property, nameof(string.Contains), Type.EmptyTypes, constant),
|
||||||
|
"StartsWith" => Expression.Call(property, nameof(string.Contains), Type.EmptyTypes, constant),
|
||||||
|
"EndsWith" => Expression.Call(property, nameof(string.Contains), Type.EmptyTypes, constant),
|
||||||
|
_ => throw new NotSupportedException($"Operator {filter.Operator} not supported.")
|
||||||
|
};
|
||||||
|
|
||||||
|
var lambda = Expression.Lambda<Func<TEntity, bool>>(body, parameter);
|
||||||
|
return query.Where(lambda);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Mf.Core.Interfaces;
|
||||||
|
using Mf.Core.SubEntities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Mf.EfCore.Services
|
||||||
|
{
|
||||||
|
public class PostgresqlContextCore : DbContext, IContextCore
|
||||||
|
{
|
||||||
|
public PostgresqlContextCore(DbContextOptions optinos) : base(optinos) { }
|
||||||
|
|
||||||
|
public List<Type>? Entities { get; set; }
|
||||||
|
|
||||||
|
public IGenericService<TypeModel> GetService<TypeModel>() where TypeModel : class, IEntity
|
||||||
|
{
|
||||||
|
var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(typeof(TypeModel));
|
||||||
|
var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) });
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
var telBotServiceInstance = constructor.Invoke(new object[] { this });
|
||||||
|
return (EntityFrameworkCoreServices<TypeModel>)telBotServiceInstance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
var telBotServiceInstance = Activator.CreateInstance(telBotServiceType);
|
||||||
|
|
||||||
|
return (EntityFrameworkCoreServices<TypeModel>)telBotServiceInstance!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetService(Type type)
|
||||||
|
{
|
||||||
|
var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type);
|
||||||
|
var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) });
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
var telBotServiceInstance = constructor.Invoke(new object[] { this });
|
||||||
|
return telBotServiceInstance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var telBotServiceInstance = Activator.CreateInstance(telBotServiceType);
|
||||||
|
return telBotServiceInstance!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public List<object> GetGenericServices(List<Type> entities)
|
||||||
|
{
|
||||||
|
List<object> services = new List<object>();
|
||||||
|
foreach (var type in entities)
|
||||||
|
{
|
||||||
|
var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type);
|
||||||
|
// Get the constructor of the TelBot_Service<T> type
|
||||||
|
var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) });
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
// If constructor exists, create an instance with a parameter
|
||||||
|
var telBotServiceInstance = constructor.Invoke(new object[] { this }); // Provide the parameter value here
|
||||||
|
//var ssss = (IGenericService<IEntity>)telBotServiceInstance;
|
||||||
|
//var sss = (EntityFrameworkCoreServices<IEntity>)telBotServiceInstance;
|
||||||
|
services.Add(telBotServiceInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If no constructor exists, create an instance without parameters
|
||||||
|
var telBotServiceInstance = Activator.CreateInstance(telBotServiceType);
|
||||||
|
//var sss = (EntityFrameworkCoreServices<IEntity>)telBotServiceInstance;
|
||||||
|
services.Add(telBotServiceInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
if (Entities != null)
|
||||||
|
{
|
||||||
|
foreach (var s in Entities)
|
||||||
|
{
|
||||||
|
var entity = modelBuilder.Entity(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//for postgres db
|
||||||
|
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||||
|
{
|
||||||
|
foreach (var property in entityType.GetProperties())
|
||||||
|
{
|
||||||
|
if (property.ClrType == typeof(DateTime))
|
||||||
|
{
|
||||||
|
property.SetValueConverter(new ValueConverter<DateTime, DateTime>(
|
||||||
|
v => v.Kind == DateTimeKind.Utc ? v : v.ToUniversalTime(), // ذخیره
|
||||||
|
v => DateTime.SpecifyKind(v, DateTimeKind.Utc) // بازیابی
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (property.ClrType == typeof(DateTime?))
|
||||||
|
{
|
||||||
|
property.SetValueConverter(new ValueConverter<DateTime?, DateTime?>(
|
||||||
|
v => v.HasValue ? (v.Value.Kind == DateTimeKind.Utc ? v : v.Value.ToUniversalTime()) : v, // ذخیره
|
||||||
|
v => v.HasValue ? DateTime.SpecifyKind(v.Value, DateTimeKind.Utc) : v // بازیابی
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void IContextCore.Dispose()
|
||||||
|
{
|
||||||
|
this.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Migrate()
|
||||||
|
{
|
||||||
|
this.Migrate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Mf.Core.Interfaces;
|
||||||
|
using Mf.Core.SubEntities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.EfCore.Services
|
||||||
|
{
|
||||||
|
public class SqlServerContextCore : DbContext, IContextCore
|
||||||
|
{
|
||||||
|
public SqlServerContextCore(DbContextOptions optinos) : base(optinos) { }
|
||||||
|
|
||||||
|
public List<Type>? Entities { get; set; }
|
||||||
|
|
||||||
|
public IGenericService<TypeModel> GetService<TypeModel>() where TypeModel : class, IEntity
|
||||||
|
{
|
||||||
|
var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(typeof(TypeModel));
|
||||||
|
var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) });
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
var telBotServiceInstance = constructor.Invoke(new object[] { this });
|
||||||
|
return (EntityFrameworkCoreServices<TypeModel>)telBotServiceInstance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
var telBotServiceInstance = Activator.CreateInstance(telBotServiceType);
|
||||||
|
|
||||||
|
return (EntityFrameworkCoreServices<TypeModel>)telBotServiceInstance!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetService(Type type)
|
||||||
|
{
|
||||||
|
var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type);
|
||||||
|
var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) });
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
var telBotServiceInstance = constructor.Invoke(new object[] { this });
|
||||||
|
return telBotServiceInstance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var telBotServiceInstance = Activator.CreateInstance(telBotServiceType);
|
||||||
|
return telBotServiceInstance!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public List<object> GetGenericServices(List<Type> entities)
|
||||||
|
{
|
||||||
|
List<object> services = new List<object>();
|
||||||
|
foreach (var type in entities)
|
||||||
|
{
|
||||||
|
var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type);
|
||||||
|
// Get the constructor of the TelBot_Service<T> type
|
||||||
|
var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqlServerContextCore) });
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
// If constructor exists, create an instance with a parameter
|
||||||
|
var telBotServiceInstance = constructor.Invoke(new object[] { this }); // Provide the parameter value here
|
||||||
|
//var ssss = (IGenericService<IEntity>)telBotServiceInstance;
|
||||||
|
//var sss = (EntityFrameworkCoreServices<IEntity>)telBotServiceInstance;
|
||||||
|
services.Add(telBotServiceInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If no constructor exists, create an instance without parameters
|
||||||
|
var telBotServiceInstance = Activator.CreateInstance(telBotServiceType);
|
||||||
|
//var sss = (EntityFrameworkCoreServices<IEntity>)telBotServiceInstance;
|
||||||
|
services.Add(telBotServiceInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
if (Entities != null)
|
||||||
|
{
|
||||||
|
foreach (var s in Entities)
|
||||||
|
{
|
||||||
|
var entity = modelBuilder.Entity(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//for postgres db
|
||||||
|
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||||
|
{
|
||||||
|
foreach (var property in entityType.GetProperties())
|
||||||
|
{
|
||||||
|
if (property.ClrType == typeof(DateTime))
|
||||||
|
{
|
||||||
|
property.SetValueConverter(new ValueConverter<DateTime, DateTime>(
|
||||||
|
v => v.Kind == DateTimeKind.Utc ? v : v.ToUniversalTime(), // ذخیره
|
||||||
|
v => DateTime.SpecifyKind(v, DateTimeKind.Utc) // بازیابی
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (property.ClrType == typeof(DateTime?))
|
||||||
|
{
|
||||||
|
property.SetValueConverter(new ValueConverter<DateTime?, DateTime?>(
|
||||||
|
v => v.HasValue ? (v.Value.Kind == DateTimeKind.Utc ? v : v.Value.ToUniversalTime()) : v, // ذخیره
|
||||||
|
v => v.HasValue ? DateTime.SpecifyKind(v.Value, DateTimeKind.Utc) : v // بازیابی
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void IContextCore.Dispose()
|
||||||
|
{
|
||||||
|
this.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Migrate()
|
||||||
|
{
|
||||||
|
this.Migrate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Mf.Core.Interfaces;
|
||||||
|
using Mf.Core.SubEntities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.EfCore.Services
|
||||||
|
{
|
||||||
|
public abstract class SqliteContextCore : DbContext, IContextCore
|
||||||
|
{
|
||||||
|
public string DbName { get; set; }
|
||||||
|
public string DbPath { get; set; }
|
||||||
|
|
||||||
|
public List<Type> Entities { get; set; }
|
||||||
|
|
||||||
|
public void SetDefaultConfig()
|
||||||
|
{
|
||||||
|
DbName = "defualt-database-name.db";
|
||||||
|
DbPath = "";
|
||||||
|
}
|
||||||
|
public SqliteContextCore(bool setDefaultConfig = true)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (setDefaultConfig)
|
||||||
|
{
|
||||||
|
SetDefaultConfig();
|
||||||
|
CreateDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public void CreateDB()
|
||||||
|
{
|
||||||
|
//TODO clean this
|
||||||
|
//var strDestination = "copy.db";
|
||||||
|
//string dir = Directory.GetCurrentDirectory();
|
||||||
|
//dir = Path.Combine(dir, strDestination);
|
||||||
|
|
||||||
|
|
||||||
|
//string orgDir = Path.Combine(Directory.GetCurrentDirectory(), DbPath, DbName);
|
||||||
|
|
||||||
|
//if (!Path.Exists(Path.Combine(Directory.GetCurrentDirectory(), DbPath)))
|
||||||
|
//{
|
||||||
|
// Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), DbPath));
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (!File.Exists(orgDir))
|
||||||
|
//{
|
||||||
|
|
||||||
|
// System.Data.SQLite.SQLiteConnection.CreateFile(orgDir);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (!File.Exists(dir))
|
||||||
|
//{
|
||||||
|
|
||||||
|
// System.Data.SQLite.SQLiteConnection.CreateFile(dir);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//using (var location = new System.Data.SQLite.SQLiteConnection(string.Format(@"Data Source={0};", orgDir)))
|
||||||
|
////using (var destination = new System.Data.SQLite.SQLiteConnection(string.Format(@"Data Source={0}", dir)))
|
||||||
|
//{
|
||||||
|
// location.Open();
|
||||||
|
// //destination.Open();
|
||||||
|
// //location.BackupDatabase(destination, "main", "main", -1, null, 0);
|
||||||
|
// //destination.Close();
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
optionsBuilder.UseSqlite($"Data Source={DbPath}{DbName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IGenericService<TypeModel> GetService<TypeModel>() where TypeModel : class, IEntity
|
||||||
|
{
|
||||||
|
var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(typeof(TypeModel));
|
||||||
|
var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqliteContextCore) });
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
var telBotServiceInstance = constructor.Invoke(new object[] { this });
|
||||||
|
return (EntityFrameworkCoreServices<TypeModel>)telBotServiceInstance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
var telBotServiceInstance = Activator.CreateInstance(telBotServiceType);
|
||||||
|
|
||||||
|
return (EntityFrameworkCoreServices<TypeModel>)telBotServiceInstance!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetService(Type type)
|
||||||
|
{
|
||||||
|
var telBotServiceType = typeof(EntityFrameworkCoreServices<>).MakeGenericType(type);
|
||||||
|
var constructor = telBotServiceType.GetConstructor(new[] { typeof(SqliteContextCore) });
|
||||||
|
if (constructor != null)
|
||||||
|
{
|
||||||
|
var telBotServiceInstance = constructor.Invoke(new object[] { this });
|
||||||
|
return telBotServiceInstance;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var telBotServiceInstance = Activator.CreateInstance(telBotServiceType);
|
||||||
|
return telBotServiceInstance!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IContextCore.Dispose()
|
||||||
|
{
|
||||||
|
this.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Migrate()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.Migrate();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
if (Entities != null)
|
||||||
|
{
|
||||||
|
foreach (var s in Entities)
|
||||||
|
{
|
||||||
|
var entity = modelBuilder.Entity(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Mf.Entity.Tables;
|
||||||
|
|
||||||
|
public interface ITable
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Mf.Entity.Tables;
|
||||||
|
|
||||||
|
public abstract class TableBase<T>:ITable
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public T? Id { get; set; }
|
||||||
|
|
||||||
|
private List<TableBase<T>>? _seedData = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Tablebase : TableBase<long>
|
||||||
|
{
|
||||||
|
|
||||||
|
public Tablebase()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Mf.Razor.Entity
|
||||||
|
{
|
||||||
|
public class Configuration
|
||||||
|
{
|
||||||
|
public int Radios { get; set; }
|
||||||
|
|
||||||
|
public Theme? Theme { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using Mf.Razor.Entity.ViewModels;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Entity.Interfaces;
|
||||||
|
|
||||||
|
public interface ICarouselService
|
||||||
|
{
|
||||||
|
public Task<CarouselVm> GetCarousel(int? carouselId = 0);
|
||||||
|
|
||||||
|
public Task<bool> ExecuteCarousel(CarouselVm carousel);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Entity.Interfaces
|
||||||
|
{
|
||||||
|
public interface IFrontLogger
|
||||||
|
{
|
||||||
|
void Log(string content, LogMode mode, TimeSpan time);
|
||||||
|
void Log(string content, LogMode mode);
|
||||||
|
void Log(string content);
|
||||||
|
|
||||||
|
List<LogModel> GetAllLogs();
|
||||||
|
|
||||||
|
void ClearLogs();
|
||||||
|
|
||||||
|
public static event EventHandler LogEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class LogModel
|
||||||
|
{
|
||||||
|
public string LogContent { get; set; }
|
||||||
|
public DateTime CreatedDate { get; set; }
|
||||||
|
public int index { get; set; }
|
||||||
|
public LogMode LogMode { get; set; }
|
||||||
|
public TimeSpan? Time { get; set; }
|
||||||
|
}
|
||||||
|
public enum LogMode
|
||||||
|
{
|
||||||
|
Info = 0,
|
||||||
|
Error = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Entity.Interfaces
|
||||||
|
{
|
||||||
|
public interface IServiceLocator
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Entity.Interfaces
|
||||||
|
{
|
||||||
|
public interface ITokenService
|
||||||
|
{
|
||||||
|
Task<string?> GetToken();
|
||||||
|
Task<bool> SetToken(string token);
|
||||||
|
Task<bool> RemoveToke();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Mf.Razor.Entity
|
||||||
|
{
|
||||||
|
public class Theme
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Entity.ViewModels;
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public class CarouselItemVm
|
||||||
|
{
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
public string? Title { get; set; }
|
||||||
|
|
||||||
|
public string? ImageAddress { get; set; }
|
||||||
|
|
||||||
|
public string? LinkAddress { get; set; }
|
||||||
|
|
||||||
|
public CarouselVm? Carousel{ get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Entity.ViewModels;
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public class CarouselVm
|
||||||
|
{
|
||||||
|
public int Height { get; set; }
|
||||||
|
|
||||||
|
public int Width { get; set; }
|
||||||
|
|
||||||
|
public List<CarouselItemVm>? Items { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Entity.ViewModels
|
||||||
|
{
|
||||||
|
[NotMapped]
|
||||||
|
public class Modal_Vm
|
||||||
|
{
|
||||||
|
public string? Title { get; set; }
|
||||||
|
public Guid Guid { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
|
||||||
|
using Blazored.LocalStorage;
|
||||||
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Mf.Razor.Entity.Interfaces;
|
||||||
|
using Mf.Razor.Services;
|
||||||
|
|
||||||
|
namespace Mf.Razor
|
||||||
|
{
|
||||||
|
public class CustomAuthStateProvider : AuthenticationStateProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly ITokenService _tokenService;
|
||||||
|
private readonly LogService _logger;
|
||||||
|
public CustomAuthStateProvider(ITokenService tokenService,LogService logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_tokenService = tokenService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetToken(string tokenKey)
|
||||||
|
{
|
||||||
|
await _tokenService.SetToken(tokenKey);
|
||||||
|
}
|
||||||
|
public async Task<bool> RemoveToke()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _tokenService.RemoveToke();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||||
|
{
|
||||||
|
string token = await _tokenService.GetToken();
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(token))
|
||||||
|
{
|
||||||
|
var state = new AuthenticationState(new ClaimsPrincipal());
|
||||||
|
NotifyAuthenticationStateChanged(Task.FromResult(state));
|
||||||
|
_logger.Log("Auth Is False");
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
tokenHandler.ValidateToken(token, new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
ValidateIssuer = false,
|
||||||
|
ValidateAudience = false,
|
||||||
|
RequireExpirationTime = true,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
// Set clock skew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later by default)
|
||||||
|
ClockSkew = TimeSpan.Zero
|
||||||
|
}, out SecurityToken validatedToken);
|
||||||
|
|
||||||
|
var jwtToken = (JwtSecurityToken)validatedToken;
|
||||||
|
|
||||||
|
// Create ClaimsPrincipal from the token's claims
|
||||||
|
var claimsIdentity = new ClaimsIdentity(jwtToken.Claims, "jwt");
|
||||||
|
var user = new ClaimsPrincipal(claimsIdentity);
|
||||||
|
var state = new AuthenticationState(user);
|
||||||
|
NotifyAuthenticationStateChanged(Task.FromResult(state));
|
||||||
|
_logger.Log("Auth is ON");
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Token validation failed
|
||||||
|
var state = new AuthenticationState(new ClaimsPrincipal());
|
||||||
|
NotifyAuthenticationStateChanged(Task.FromResult(state));
|
||||||
|
_logger.Log("Auth Is False");
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
|
||||||
|
{
|
||||||
|
var payload = jwt.Split('.')[1];
|
||||||
|
var jsonBytes = ParseBase64WithoutPadding(payload);
|
||||||
|
var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);
|
||||||
|
return keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] ParseBase64WithoutPadding(string base64)
|
||||||
|
{
|
||||||
|
switch (base64.Length % 4)
|
||||||
|
{
|
||||||
|
case 2: base64 += "=="; break;
|
||||||
|
case 3: base64 += "="; break;
|
||||||
|
}
|
||||||
|
return Convert.FromBase64String(base64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Mf.Razor
|
||||||
|
{
|
||||||
|
public static class JwtService
|
||||||
|
{
|
||||||
|
//static string securityAlgorithm = SecurityAlgorithms.HmacSha512Signature;
|
||||||
|
public static string CreateJwtToken(string securityKey, List<Claim> claims, TimeSpan? expireDate = null)
|
||||||
|
{
|
||||||
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey));
|
||||||
|
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
var expires = new DateTime();
|
||||||
|
if(expireDate == null)
|
||||||
|
{
|
||||||
|
expires = DateTime.Now.AddDays(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expires = DateTime.Now.AddMinutes(expireDate.Value.TotalMinutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = new JwtSecurityToken(
|
||||||
|
"daliranpv.ir",
|
||||||
|
"your_audience",
|
||||||
|
claims,
|
||||||
|
expires: expires,
|
||||||
|
signingCredentials: creds
|
||||||
|
);
|
||||||
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
|
|
||||||
|
|
||||||
|
//var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
//var key = Encoding.ASCII.GetBytes(Tokens.AuthenticaitonSystemOne.Key);
|
||||||
|
//var tokenDescriptor = new SecurityTokenDescriptor
|
||||||
|
//{
|
||||||
|
// Subject = new ClaimsIdentity(claims),
|
||||||
|
// Expires = DateTime.UtcNow.AddDays(7),
|
||||||
|
// SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||||
|
//};
|
||||||
|
//var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||||
|
//return tokenHandler.WriteToken(token);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<div class="my-component">
|
||||||
|
This component is defined in the <strong>Mf.Razor</strong> library.
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
.my-component {
|
||||||
|
border: 2px dashed red;
|
||||||
|
padding: 1em;
|
||||||
|
margin: 1em 0;
|
||||||
|
background-image: url('background.png');
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<div id="carouselExampleAutoplaying" class="carousel slide" data-bs-ride="carousel">
|
||||||
|
<div class="carousel-inner">
|
||||||
|
<div class="carousel-item active">
|
||||||
|
<img src="carousel-content/felo.jpg" class="d-block w-100" alt="...">
|
||||||
|
</div>
|
||||||
|
<div class="carousel-item">
|
||||||
|
<img src="carousel-content/ketabesal.jpg" class="d-block w-100" alt="...">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleAutoplaying" data-bs-slide="prev">
|
||||||
|
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||||
|
<span class="visually-hidden">Previous</span>
|
||||||
|
</button>
|
||||||
|
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleAutoplaying" data-bs-slide="next">
|
||||||
|
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||||
|
<span class="visually-hidden">Next</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/* GLOBAL STYLES
|
||||||
|
-------------------------------------------------- */
|
||||||
|
/* Padding below the footer and lighter body text */
|
||||||
|
|
||||||
|
/* CUSTOMIZE THE CAROUSEL
|
||||||
|
-------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Carousel base class */
|
||||||
|
.carousel {
|
||||||
|
margin-top:1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
/* Since positioning the image, we need to help out the caption */
|
||||||
|
.carousel-caption {
|
||||||
|
bottom: 3rem;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Declare heights because of positioning of img element */
|
||||||
|
.carousel-item {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* MARKETING CONTENT
|
||||||
|
-------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Center align the text within the three columns below the carousel */
|
||||||
|
.marketing .col-lg-4 {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.marketing .col-lg-4 p {
|
||||||
|
margin-right: .75rem;
|
||||||
|
margin-left: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Featurettes
|
||||||
|
------------------------- */
|
||||||
|
|
||||||
|
.featurette-divider {
|
||||||
|
margin: 5rem 0; /* Space out the Bootstrap <hr> more */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Thin out the marketing headings */
|
||||||
|
|
||||||
|
/* RESPONSIVE CSS
|
||||||
|
-------------------------------------------------- */
|
||||||
|
|
||||||
|
@media (min-width: 40em) {
|
||||||
|
/* Bump up size of carousel content */
|
||||||
|
.carousel-caption p {
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.featurette-heading {
|
||||||
|
font-size: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 62em) {
|
||||||
|
.featurette-heading {
|
||||||
|
margin-top: 7rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
@using System.Globalization
|
||||||
|
@typeparam T
|
||||||
|
|
||||||
|
@* <input type="text"
|
||||||
|
inputmode="numeric"
|
||||||
|
pattern="[0-9\s]{13,19}"
|
||||||
|
autocomplete="cc-number"
|
||||||
|
maxlength="19"
|
||||||
|
placeholder="xxxx xxxx xxxx xxxx" />
|
||||||
|
*@
|
||||||
|
|
||||||
|
<input type="text" class="@Class"
|
||||||
|
inputmode="numeric"
|
||||||
|
value="@formattedValue"
|
||||||
|
onfocus="this.select()"
|
||||||
|
@oninput="OnInputChanged"
|
||||||
|
@onblur="OnBlur"
|
||||||
|
/>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter]
|
||||||
|
public T Value { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<T> ValueChanged { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? Class { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? Id { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? PlaceHolder { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
private string formattedValue = "";
|
||||||
|
|
||||||
|
protected override void OnParametersSet()
|
||||||
|
{
|
||||||
|
formattedValue = FormatValue(Value);
|
||||||
|
}
|
||||||
|
private void OnInputChanged(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var raw = e.Value?.ToString()?.Replace(",", "").Trim() ?? "0";
|
||||||
|
|
||||||
|
var sss = new string(raw.Where(char.IsDigit).ToArray());
|
||||||
|
if (string.IsNullOrEmpty(sss))
|
||||||
|
{
|
||||||
|
formattedValue = "0";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object? parsed = typeof(T) switch
|
||||||
|
{
|
||||||
|
var t when t == typeof(int) && int.TryParse(raw, out var intVal) => intVal,
|
||||||
|
var t when t == typeof(long) && long.TryParse(raw, out var longVal) => longVal,
|
||||||
|
var t when t == typeof(decimal) && decimal.TryParse(raw, out var decVal) => decVal,
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (parsed is T tValue)
|
||||||
|
{
|
||||||
|
ValueChanged.InvokeAsync(tValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
formattedValue = raw; // temporary display while editing
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBlur()
|
||||||
|
{
|
||||||
|
formattedValue = FormatValue(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFocus()
|
||||||
|
{
|
||||||
|
formattedValue = FormatValue(Value);
|
||||||
|
// formattedValue = Value?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatValue(T val)
|
||||||
|
{
|
||||||
|
if (val == null) return "";
|
||||||
|
return val switch
|
||||||
|
{
|
||||||
|
int i => i.ToString("N0", CultureInfo.InvariantCulture),
|
||||||
|
long l => l.ToString("N0", CultureInfo.InvariantCulture),
|
||||||
|
decimal d => d.ToString("N0", CultureInfo.InvariantCulture),
|
||||||
|
_ => val.ToString() ?? ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
namespace Mf.Razor.Events
|
||||||
|
{
|
||||||
|
public delegate void ServiceLocatorDelegate();
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using Microsoft.JSInterop;
|
||||||
|
|
||||||
|
namespace Mf.Razor;
|
||||||
|
|
||||||
|
// This class provides an example of how JavaScript functionality can be wrapped
|
||||||
|
// in a .NET class for easy consumption. The associated JavaScript module is
|
||||||
|
// loaded on demand when first needed.
|
||||||
|
//
|
||||||
|
// This class can be registered as scoped DI service and then injected into Blazor
|
||||||
|
// components for use.
|
||||||
|
|
||||||
|
public class ExampleJsInterop(IJSRuntime jsRuntime) : IAsyncDisposable
|
||||||
|
{
|
||||||
|
private readonly Lazy<Task<IJSObjectReference>> moduleTask = new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
|
||||||
|
"import", "./_content/Mf.Razor/exampleJsInterop.js").AsTask());
|
||||||
|
|
||||||
|
public async ValueTask<string> Prompt(string message)
|
||||||
|
{
|
||||||
|
var module = await moduleTask.Value;
|
||||||
|
return await module.InvokeAsync<string>("showPrompt", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
if (moduleTask.IsValueCreated)
|
||||||
|
{
|
||||||
|
var module = await moduleTask.Value;
|
||||||
|
await module.DisposeAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Mf.Razor.Interfaces
|
||||||
|
{
|
||||||
|
public interface IModalService
|
||||||
|
{
|
||||||
|
public void Show();
|
||||||
|
|
||||||
|
public void Hide();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Mf.Razor.Interfaces
|
||||||
|
{
|
||||||
|
public interface IServiceLocator
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<SupportedPlatform Include="browser"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="10.0.0"/>
|
||||||
|
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="10.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.15.0" />
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.15.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Mf.Razor.Entity\Mf.Razor.Entity.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Mf.Razor.Entity.Interfaces;
|
||||||
|
using Mf.Razor.Services;
|
||||||
|
|
||||||
|
namespace Mf.Razor
|
||||||
|
{
|
||||||
|
public static class RazorProvider
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddBootstrap5(this IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
return serviceCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddAuthentication(this IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
return serviceCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddLogger(this IServiceCollection serviceCollection)
|
||||||
|
{
|
||||||
|
serviceCollection.AddSingleton<IFrontLogger, LogService>();
|
||||||
|
serviceCollection.AddSingleton<LogService>();
|
||||||
|
return serviceCollection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
using Mf.Razor.Entity.Interfaces;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Services
|
||||||
|
{
|
||||||
|
public class LogService:IFrontLogger
|
||||||
|
{
|
||||||
|
private int indexer = 1;
|
||||||
|
public event EventHandler LogEvent;
|
||||||
|
private List<LogModel> LogComments { get; set; } = new List<LogModel>();
|
||||||
|
|
||||||
|
public virtual void Log(string content, LogMode mode, TimeSpan time)
|
||||||
|
{
|
||||||
|
LogComments.Add(new LogModel { CreatedDate = DateTime.Now,index = indexer,LogContent = content,LogMode = mode,Time = time});
|
||||||
|
indexer++;
|
||||||
|
LogEvent?.Invoke(null, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Log(string content, LogMode mode)
|
||||||
|
{
|
||||||
|
LogComments.Add(new LogModel { CreatedDate = DateTime.Now, index = indexer, LogContent = content, LogMode = mode, Time = null });
|
||||||
|
indexer++;
|
||||||
|
LogEvent?.Invoke(null, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Log(string content)
|
||||||
|
{
|
||||||
|
LogComments.Add(new LogModel { CreatedDate = DateTime.Now, index = indexer, LogContent = content, LogMode = LogMode.Info, Time = null });
|
||||||
|
indexer++;
|
||||||
|
LogEvent?.Invoke(null, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual List<LogModel> GetAllLogs()
|
||||||
|
{
|
||||||
|
return LogComments.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ClearLogs()
|
||||||
|
{
|
||||||
|
LogComments = new List<LogModel>();
|
||||||
|
indexer = 0;
|
||||||
|
Log("Clear Logs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
using Mf.Razor.Entity.Interfaces;
|
||||||
|
using Mf.Razor.Interfaces;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Services
|
||||||
|
{
|
||||||
|
public class RequestService
|
||||||
|
{
|
||||||
|
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1); // دو درخواست همزمان
|
||||||
|
|
||||||
|
public async Task<T> ExecuteAsync<T>(Func<Task<T>> action)
|
||||||
|
{
|
||||||
|
await _semaphore.WaitAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await action();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.ToString());
|
||||||
|
//ServiceLocator.Log($"Error Limiter : {ex.Message}");
|
||||||
|
return await action();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
//ServiceLocator.Log($"Relase : {DateTime.Now.ToString()}");
|
||||||
|
_semaphore.Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ExecuteAsync(Func<Task> action)
|
||||||
|
{
|
||||||
|
await _semaphore.WaitAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await action();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.ToString());
|
||||||
|
//ServiceLocator.Log($"Error Limiter : {ex.Message}");
|
||||||
|
await action();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
//ServiceLocator.Log($"Relase : {DateTime.Now.ToString()}");
|
||||||
|
_semaphore.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using Mf.Razor.Events;
|
||||||
|
using Mf.Razor.Interfaces;
|
||||||
|
|
||||||
|
namespace Mf.Razor.Services
|
||||||
|
{
|
||||||
|
internal abstract class ServiceLocator : IServiceLocator
|
||||||
|
{
|
||||||
|
internal IServiceProvider _serviceProvider;
|
||||||
|
protected ServiceLocator(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
private event ServiceLocatorDelegate? Update;
|
||||||
|
public int EventNumbers { get; private set; } = 0;
|
||||||
|
public virtual Task InvokeUpdate()
|
||||||
|
{
|
||||||
|
Update?.Invoke();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void AddEvent(ServiceLocatorDelegate input)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Update += input;
|
||||||
|
EventNumbers++;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void RemoveEvent(ServiceLocatorDelegate input)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Update -= input;
|
||||||
|
EventNumbers--;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
@using Microsoft.AspNetCore.Components.Web
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 378 B |
@@ -0,0 +1,6 @@
|
|||||||
|
// This is a JavaScript module that is loaded on demand. It can export any number of
|
||||||
|
// functions, and may import other JavaScript modules if required.
|
||||||
|
|
||||||
|
export function showPrompt(message) {
|
||||||
|
return prompt(message, 'Type anything here');
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Core", "Mf.Core\Mf.Core.csproj", "{365652A1-EDFD-4102-B9FD-117EACFCCCC6}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Entity", "Mf.Entity\Mf.Entity.csproj", "{BE3FD258-BC5E-45F5-831C-7EAFB37D398C}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Ef", "Mf.Ef\Mf.Ef.csproj", "{9D5D4C17-9C3E-4104-8A87-7AB660B71762}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Razors", "Razors", "{5493F5AB-AEC8-4D51-AC9E-513C1505D8A2}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{ED63E99B-0EF8-4CEB-B4B5-BE795DE9FF78}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Razor", "Mf.Razor\Mf.Razor.csproj", "{09763D74-4477-47A8-AE59-B9E90D9AD64F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mf.Razor.Entity", "Mf.Razor.Entity\Mf.Razor.Entity.csproj", "{9FADD8A4-A17E-4F24-96D6-E58D66471324}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{365652A1-EDFD-4102-B9FD-117EACFCCCC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{365652A1-EDFD-4102-B9FD-117EACFCCCC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{365652A1-EDFD-4102-B9FD-117EACFCCCC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{365652A1-EDFD-4102-B9FD-117EACFCCCC6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BE3FD258-BC5E-45F5-831C-7EAFB37D398C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BE3FD258-BC5E-45F5-831C-7EAFB37D398C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BE3FD258-BC5E-45F5-831C-7EAFB37D398C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BE3FD258-BC5E-45F5-831C-7EAFB37D398C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9D5D4C17-9C3E-4104-8A87-7AB660B71762}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9D5D4C17-9C3E-4104-8A87-7AB660B71762}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9D5D4C17-9C3E-4104-8A87-7AB660B71762}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9D5D4C17-9C3E-4104-8A87-7AB660B71762}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{09763D74-4477-47A8-AE59-B9E90D9AD64F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{09763D74-4477-47A8-AE59-B9E90D9AD64F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{09763D74-4477-47A8-AE59-B9E90D9AD64F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{09763D74-4477-47A8-AE59-B9E90D9AD64F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9FADD8A4-A17E-4F24-96D6-E58D66471324}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9FADD8A4-A17E-4F24-96D6-E58D66471324}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9FADD8A4-A17E-4F24-96D6-E58D66471324}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9FADD8A4-A17E-4F24-96D6-E58D66471324}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{ED63E99B-0EF8-4CEB-B4B5-BE795DE9FF78} = {5493F5AB-AEC8-4D51-AC9E-513C1505D8A2}
|
||||||
|
{09763D74-4477-47A8-AE59-B9E90D9AD64F} = {ED63E99B-0EF8-4CEB-B4B5-BE795DE9FF78}
|
||||||
|
{9FADD8A4-A17E-4F24-96D6-E58D66471324} = {ED63E99B-0EF8-4CEB-B4B5-BE795DE9FF78}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
Reference in New Issue
Block a user