From 4f08b1f6e2470b946f018cb34cc87df5e884265f Mon Sep 17 00:00:00 2001 From: falcon <9504402@qq.com> Date: Mon, 26 Aug 2019 09:23:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=93=E5=BA=93=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E3=80=82=E5=8C=85=E5=90=ABDI=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 263 ++++++++++++++++++ .../Falcon.AutoTableLog.Test.csproj | 21 ++ Falcon.AutoTableLog.Test/MyDbContext.cs | 27 ++ Falcon.AutoTableLog.Test/UnitTest1.cs | 21 ++ Falcon.AutoTableLog/DbContextAutoSaveLog.cs | 27 ++ .../Falcon.AutoTableLog.csproj | 10 + Falcon.Cache/Falcon.Cache.csproj | 17 ++ Falcon.DI.Packget.Test/Falcon.DI.cs | 24 ++ .../Falcon.Packget.Test.csproj | 17 ++ Falcon.DI.Test/DITest.cs | 120 ++++++++ Falcon.DI.Test/Falcon.DI.Test.csproj | 20 ++ Falcon.DI.Test/FalconDIInstantType.cs | 33 +++ Falcon.DI.Test/IMyInterface.cs | 44 +++ Falcon.DI.Test/MyClassWithDisable.cs | 20 ++ Falcon.DI.Test/NotFull.cs | 22 ++ Falcon.DI.Test/RegisterToSelf.cs | 11 + Falcon.DI.Test/SingletonTest.cs | 8 + Falcon.DI/Falcon.DI.csproj | 17 ++ Falcon.DI/Falcon.DI.xml | 45 +++ Falcon.DI/FalconDIRegisterAttribute.cs | 30 ++ Falcon.DI/IFalconDIInstantFactory.cs | 15 + Falcon.DI/IServiceCollectionExtend.cs | 48 ++++ .../PublishProfiles/FolderProfile.pubxml | 13 + Falcon.DI/ServiceLifetime.cs | 21 ++ Falcon.ModelSP/DadaContextExtend.cs | 125 +++++++++ Falcon.ModelSP/Falcon.ModelSP.csproj | 12 + Falcon.ModelSP/FalconSPIgnoreAttribute.cs | 11 + Falcon.ModelSP/FalconSPPrarmNameAttribute.cs | 13 + .../FalconSPProcuderNameAttribute.cs | 14 + Falcon.ModelSP/IFalconSPRuner.cs | 45 +++ Falcon.ModelSP/IServiceCollectionExtend.cs | 22 ++ Falcon.ModelSP/ProcuderNotFoundException.cs | 12 + FalconCore.sln | 67 +++++ MS.ResidCache.Test/MS.ResidCache.Test.csproj | 17 ++ MS.ResidCache.Test/MS_MemeryCacheUnitTest.cs | 32 +++ .../MicrosoftRedisCacheUnitTest.cs | 29 ++ 36 files changed, 1293 insertions(+) create mode 100644 .gitignore create mode 100644 Falcon.AutoTableLog.Test/Falcon.AutoTableLog.Test.csproj create mode 100644 Falcon.AutoTableLog.Test/MyDbContext.cs create mode 100644 Falcon.AutoTableLog.Test/UnitTest1.cs create mode 100644 Falcon.AutoTableLog/DbContextAutoSaveLog.cs create mode 100644 Falcon.AutoTableLog/Falcon.AutoTableLog.csproj create mode 100644 Falcon.Cache/Falcon.Cache.csproj create mode 100644 Falcon.DI.Packget.Test/Falcon.DI.cs create mode 100644 Falcon.DI.Packget.Test/Falcon.Packget.Test.csproj create mode 100644 Falcon.DI.Test/DITest.cs create mode 100644 Falcon.DI.Test/Falcon.DI.Test.csproj create mode 100644 Falcon.DI.Test/FalconDIInstantType.cs create mode 100644 Falcon.DI.Test/IMyInterface.cs create mode 100644 Falcon.DI.Test/MyClassWithDisable.cs create mode 100644 Falcon.DI.Test/NotFull.cs create mode 100644 Falcon.DI.Test/RegisterToSelf.cs create mode 100644 Falcon.DI.Test/SingletonTest.cs create mode 100644 Falcon.DI/Falcon.DI.csproj create mode 100644 Falcon.DI/Falcon.DI.xml create mode 100644 Falcon.DI/FalconDIRegisterAttribute.cs create mode 100644 Falcon.DI/IFalconDIInstantFactory.cs create mode 100644 Falcon.DI/IServiceCollectionExtend.cs create mode 100644 Falcon.DI/Properties/PublishProfiles/FolderProfile.pubxml create mode 100644 Falcon.DI/ServiceLifetime.cs create mode 100644 Falcon.ModelSP/DadaContextExtend.cs create mode 100644 Falcon.ModelSP/Falcon.ModelSP.csproj create mode 100644 Falcon.ModelSP/FalconSPIgnoreAttribute.cs create mode 100644 Falcon.ModelSP/FalconSPPrarmNameAttribute.cs create mode 100644 Falcon.ModelSP/FalconSPProcuderNameAttribute.cs create mode 100644 Falcon.ModelSP/IFalconSPRuner.cs create mode 100644 Falcon.ModelSP/IServiceCollectionExtend.cs create mode 100644 Falcon.ModelSP/ProcuderNotFoundException.cs create mode 100644 FalconCore.sln create mode 100644 MS.ResidCache.Test/MS.ResidCache.Test.csproj create mode 100644 MS.ResidCache.Test/MS_MemeryCacheUnitTest.cs create mode 100644 MS.ResidCache.Test/MicrosoftRedisCacheUnitTest.cs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e7dc26f --- /dev/null +++ b/.gitignore @@ -0,0 +1,263 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +zx_web/Files/errs/ + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.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 + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# 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 +# TODO: 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 +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable 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 + +# 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 +node_modules/ +orleans.codegen.cs + +# 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 + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# 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/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/Falcon.AutoTableLog.Test/Falcon.AutoTableLog.Test.csproj b/Falcon.AutoTableLog.Test/Falcon.AutoTableLog.Test.csproj new file mode 100644 index 0000000..ca8eb86 --- /dev/null +++ b/Falcon.AutoTableLog.Test/Falcon.AutoTableLog.Test.csproj @@ -0,0 +1,21 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + + + + diff --git a/Falcon.AutoTableLog.Test/MyDbContext.cs b/Falcon.AutoTableLog.Test/MyDbContext.cs new file mode 100644 index 0000000..509ccad --- /dev/null +++ b/Falcon.AutoTableLog.Test/MyDbContext.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.EntityFrameworkCore; + +namespace Falcon.AutoTableLog.Test +{ + public static class MyDbContextFactory + { + public static MyDbContext Create() { + var option = new DbContextOptionsBuilder().UseInMemoryDatabase("MemDb").Options; + return new MyDbContext(option); + } + } + + public class MyDbContext:DbContext + { + public MyDbContext(DbContextOptions options) : base(options) { } + + public DbSet People { get; set; } + } + + [Table("Person")] + public class Person + { + public int Id { get; set; } + public string Name { get; set; } + } +} diff --git a/Falcon.AutoTableLog.Test/UnitTest1.cs b/Falcon.AutoTableLog.Test/UnitTest1.cs new file mode 100644 index 0000000..0ab4b5a --- /dev/null +++ b/Falcon.AutoTableLog.Test/UnitTest1.cs @@ -0,0 +1,21 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Falcon.AutoTableLog.Test +{ + [TestClass] + public class DbContextAutoSaveLogTest + { + [TestMethod] + public void GetDbContextEventTest() { + using(var db=new MyDbContext()) { + var log = new DbContextAutoSaveLog(db); + log.GetDbContextEvent(); + + + var newP = new Person { Name = "p1"}; + db.Add(newP); + db.SaveChangesAsync().Wait(); + } + } + } +} diff --git a/Falcon.AutoTableLog/DbContextAutoSaveLog.cs b/Falcon.AutoTableLog/DbContextAutoSaveLog.cs new file mode 100644 index 0000000..8e0cb62 --- /dev/null +++ b/Falcon.AutoTableLog/DbContextAutoSaveLog.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using System.Linq; +using Microsoft.EntityFrameworkCore.ChangeTracking; + +namespace Falcon.AutoTableLog +{ + public class DbContextAutoSaveLog where TDbContext : DbContext + { + public TDbContext Db { get; set; } + + public DbContextAutoSaveLog(TDbContext db) { + this.Db = db; + } + + public void GetDbContextEvent() { + this.Db.ChangeTracker.Tracked += (object sender,EntityTrackedEventArgs e) => { + var a = e.Entry.OriginalValues; + }; + foreach(var en in this.Db.ChangeTracker.Entries()) { + } + } + + } +} diff --git a/Falcon.AutoTableLog/Falcon.AutoTableLog.csproj b/Falcon.AutoTableLog/Falcon.AutoTableLog.csproj new file mode 100644 index 0000000..36088b5 --- /dev/null +++ b/Falcon.AutoTableLog/Falcon.AutoTableLog.csproj @@ -0,0 +1,10 @@ + + + + netstandard2.0;NET461 + + + + + + diff --git a/Falcon.Cache/Falcon.Cache.csproj b/Falcon.Cache/Falcon.Cache.csproj new file mode 100644 index 0000000..210cb69 --- /dev/null +++ b/Falcon.Cache/Falcon.Cache.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.2;NET461;NET472 + true + 缓冲组件,实现对数据的缓冲 + + + + C:\Documentation\develop\FalconCore\Falcon.Cache\Falcon.Cache.xml + + + + + + + diff --git a/Falcon.DI.Packget.Test/Falcon.DI.cs b/Falcon.DI.Packget.Test/Falcon.DI.cs new file mode 100644 index 0000000..c5b9927 --- /dev/null +++ b/Falcon.DI.Packget.Test/Falcon.DI.cs @@ -0,0 +1,24 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Falcon.DI; +using Microsoft.Extensions.DependencyInjection; + +namespace Falcon.DI.Packget.Test +{ + [TestClass] + public class FalconDITest + { + [TestMethod] + public void RunTest() { + IServiceCollection ser = new ServiceCollection(); + ser.UseFalconDI(); + var pd = ser.BuildServiceProvider(); + IA obj = pd.GetService(); + Assert.IsNotNull(obj); + } + } + + public interface IA { } + + [FalconDIRegister] + public class A:IA { } +} diff --git a/Falcon.DI.Packget.Test/Falcon.Packget.Test.csproj b/Falcon.DI.Packget.Test/Falcon.Packget.Test.csproj new file mode 100644 index 0000000..cfc85fb --- /dev/null +++ b/Falcon.DI.Packget.Test/Falcon.Packget.Test.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + diff --git a/Falcon.DI.Test/DITest.cs b/Falcon.DI.Test/DITest.cs new file mode 100644 index 0000000..162b30c --- /dev/null +++ b/Falcon.DI.Test/DITest.cs @@ -0,0 +1,120 @@ +using System.Linq; +using System.Reflection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Falcon.DI.Test +{ + [TestClass] + public class UseFalconDITest + { + /// + /// һȡ + /// + [TestMethod] + public void DITest() { + IServiceCollection ser = new ServiceCollection(); + ser.UseFalconDI(); + using(var pd = ser.BuildServiceProvider()) { + Assert.IsNotNull(pd.GetServices()); + System.Console.WriteLine(pd.GetServices().Count()); + Assert.IsTrue(pd.GetServices().Count() > 1); + Assert.IsNotNull(pd.GetService()); + } + } + + /// + /// ͷԴ + /// + [TestMethod] + public void disableTest() { + IServiceCollection ser = new ServiceCollection(); + ser.UseFalconDI(); + var pd = ser.BuildServiceProvider(); + + var obj = pd.GetService(); + Assert.IsNotNull(obj); + Assert.AreEqual(1,MyClassWithDisable.Count); + + pd.Dispose(); + Assert.AreEqual(0,MyClassWithDisable.Count); + + using(pd = ser.BuildServiceProvider()) { + obj = pd.GetService(); + Assert.IsNotNull(obj); + Assert.AreEqual(1,MyClassWithDisable.Count); + } + Assert.AreEqual(0,MyClassWithDisable.Count); + } + + [TestMethod] + [Description("Բṩע")] + public void NotFullTest() { + IServiceCollection ser = new ServiceCollection(); + ser.UseFalconDI(); + var pd = ser.BuildServiceProvider(); + + var obj = pd.GetService(); + Assert.IsNotNull(obj); + Assert.IsNotNull(obj.F1); + Assert.IsNull(obj.F2); + } + + /// + /// Է񹤳 + /// + [TestMethod] + public void IFalconDIFactoryTest() { + IServiceCollection ser = new ServiceCollection(); + ser.UseFalconDI(); + using(var pd = ser.BuildServiceProvider()) { + var obj = pd.GetService(); + Assert.IsNotNull(obj); + Assert.AreEqual(obj.Instance().Val,2); + + var obj2 = pd.GetService>(); + Assert.IsNotNull(obj2); + Assert.AreEqual(obj2.Instance().Val,2); + + } + } + + /// + /// עᵽ + /// + [TestMethod] + public void RegisterToSelf() { + IServiceCollection ser = new ServiceCollection(); + ser.UseFalconDI(); + using(var pd = ser.BuildServiceProvider()) { + var obj = pd.GetService(); + Assert.IsNotNull(obj); + } + } + + /// + /// Ե + /// + [TestMethod] + public void SingletonTest() { + IServiceCollection ser = new ServiceCollection(); + ser.UseFalconDI(); + //λȡΪͬһ + using(var pd = ser.BuildServiceProvider()) { + var obj = pd.GetService(); + Assert.IsTrue(obj.Val == 0); + obj.Val = 1; + var obj2 = pd.GetService(); + Assert.IsTrue(obj.Val == 1); + } + //ͷProviderͷŵ + using(var pd = ser.BuildServiceProvider()) { + var obj = pd.GetService(); + Assert.IsTrue(obj.Val == 0); + obj.Val = 1; + var obj2 = pd.GetService(); + Assert.IsTrue(obj.Val == 1); + } + } + } +} diff --git a/Falcon.DI.Test/Falcon.DI.Test.csproj b/Falcon.DI.Test/Falcon.DI.Test.csproj new file mode 100644 index 0000000..b553e24 --- /dev/null +++ b/Falcon.DI.Test/Falcon.DI.Test.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + + + + diff --git a/Falcon.DI.Test/FalconDIInstantType.cs b/Falcon.DI.Test/FalconDIInstantType.cs new file mode 100644 index 0000000..fc5d6db --- /dev/null +++ b/Falcon.DI.Test/FalconDIInstantType.cs @@ -0,0 +1,33 @@ +using System; + +namespace Falcon.DI.Test +{ + public interface IFDIIT + { + int Val { get; set; } + } + + [FalconDIRegister] + public class FalconDIInstantType:IFDIIT + { + public int Val { get; set; } = 1; + } + + + public interface IFalconDIInstantTypeFactory:IFalconDIInstantFactory { } + + [FalconDIRegister] + public class FalconDIInstantTypeFactory:IFalconDIInstantTypeFactory, IFalconDIInstantFactory + { + public IServiceProvider Provider { get; set; } + + public FalconDIInstantTypeFactory(IServiceProvider sp = null) { + this.Provider = sp; + } + + public IFDIIT Instance() { + return this.Provider == null ? new FalconDIInstantType { Val = 3 } : + new FalconDIInstantType { Val = 2 }; + } + } +} diff --git a/Falcon.DI.Test/IMyInterface.cs b/Falcon.DI.Test/IMyInterface.cs new file mode 100644 index 0000000..8b599e4 --- /dev/null +++ b/Falcon.DI.Test/IMyInterface.cs @@ -0,0 +1,44 @@ +namespace Falcon.DI.Test +{ + public interface IMyInterface + { + string Getname(); + } + + public interface IMyInterface2 + { + string Getname(); + } + + [FalconDIRegister(typeof(IMyInterface))] + public class MyClassInterface:IMyInterface + { + public string Getname() { + return this.GetType().Name; + } + } + + [FalconDIRegister] + public class MyClassInterfaces:IMyInterface, IMyInterface2 + { + public string Getname() { + return this.GetType().Name; + } + } + + [FalconDIRegister] + public class MyClassDefault:IMyInterface + { + public string Getname() { + return this.GetType().Name; + } + } + + [FalconDIRegister(typeof(MyClassSelf))] + public class MyClassSelf:IMyInterface + { + public string Getname() { + return this.GetType().Name; + } + } +} diff --git a/Falcon.DI.Test/MyClassWithDisable.cs b/Falcon.DI.Test/MyClassWithDisable.cs new file mode 100644 index 0000000..58e447f --- /dev/null +++ b/Falcon.DI.Test/MyClassWithDisable.cs @@ -0,0 +1,20 @@ + +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.DependencyInjection; + +namespace Falcon.DI.Test +{ + [FalconDIRegister(typeof(MyClassWithDisable),Lifetime =ServiceLifetime.Transient)] + public class MyClassWithDisable:IDisposable + { + public static int Count { get; set; } = 0; + + public MyClassWithDisable() => Count += 1; + + public void Dispose() { + Count -= 1; + } + } +} diff --git a/Falcon.DI.Test/NotFull.cs b/Falcon.DI.Test/NotFull.cs new file mode 100644 index 0000000..3c98c28 --- /dev/null +++ b/Falcon.DI.Test/NotFull.cs @@ -0,0 +1,22 @@ +namespace Falcon.DI.Test +{ + public interface INfi1 { } + public interface INfi2 { } + + [FalconDIRegister] + public class NotFull:INfi1 + { + } + + [FalconDIRegister(typeof(NotFullObj))] + public class NotFullObj + { + public INfi1 F1 { get; set; } + public INfi2 F2 { get; set; } + + public NotFullObj(INfi1 f1,INfi2 f2=null) { + this.F1 = f1; + this.F2 = f2; + } + } +} diff --git a/Falcon.DI.Test/RegisterToSelf.cs b/Falcon.DI.Test/RegisterToSelf.cs new file mode 100644 index 0000000..67b8cc5 --- /dev/null +++ b/Falcon.DI.Test/RegisterToSelf.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Falcon.DI.Test +{ + [FalconDIRegister] + class RegisterToSelf + { + } +} diff --git a/Falcon.DI.Test/SingletonTest.cs b/Falcon.DI.Test/SingletonTest.cs new file mode 100644 index 0000000..e3de758 --- /dev/null +++ b/Falcon.DI.Test/SingletonTest.cs @@ -0,0 +1,8 @@ +namespace Falcon.DI.Test +{ + [FalconDIRegister(Lifetime = ServiceLifetime.Singleton)] + class SingletonTest + { + public int Val { get; set; } = 0; + } +} diff --git a/Falcon.DI/Falcon.DI.csproj b/Falcon.DI/Falcon.DI.csproj new file mode 100644 index 0000000..03f16a8 --- /dev/null +++ b/Falcon.DI/Falcon.DI.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.2;NET461;netstandard2.0 + true + 对.NET CORE进行扩展,加入FalconDIRegisterAttribute特性进行服务注册。 + + + + C:\Documentation\develop\FalconCore\Falcon.DI\Falcon.DI.xml + + + + + + + diff --git a/Falcon.DI/Falcon.DI.xml b/Falcon.DI/Falcon.DI.xml new file mode 100644 index 0000000..c7ae5d3 --- /dev/null +++ b/Falcon.DI/Falcon.DI.xml @@ -0,0 +1,45 @@ + + + + Falcon.DI + + + + + 自动注册服务特性 + + + + + 默认注册到所有实现的基础接口 + + + + + 注册到提供的服务类型 + + 服务类型 + + + + 注册的服务类型集合 + + + + + 生命周期 + + + + + 服务集合方法扩展 + + + + + 实现自动DI注册 + + 服务集合 + + + diff --git a/Falcon.DI/FalconDIRegisterAttribute.cs b/Falcon.DI/FalconDIRegisterAttribute.cs new file mode 100644 index 0000000..7ce88a9 --- /dev/null +++ b/Falcon.DI/FalconDIRegisterAttribute.cs @@ -0,0 +1,30 @@ +using System; + +namespace Falcon.DI +{ + /// + /// 自动注册服务特性。如果要注册到特定服务可以指定,否则注册到所有实现的接口服务,如果未实现任何接口注册到类型本身。 + /// + [AttributeUsage(AttributeTargets.Class)] + public class FalconDIRegisterAttribute:Attribute + { + /// + /// 默认注册到所有实现的基础接口 + /// + public FalconDIRegisterAttribute() { } + /// + /// 注册到提供的服务类型 + /// + /// 服务类型 + public FalconDIRegisterAttribute(params Type[] type) => this.ServiceTypes = type; + + /// + /// 注册的服务类型集合 + /// + public Type[] ServiceTypes { get; set; } = null; + /// + /// 生命周期 + /// + public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Scoped; + } +} diff --git a/Falcon.DI/IFalconDIInstantFactory.cs b/Falcon.DI/IFalconDIInstantFactory.cs new file mode 100644 index 0000000..11e7b09 --- /dev/null +++ b/Falcon.DI/IFalconDIInstantFactory.cs @@ -0,0 +1,15 @@ +using System; + +namespace Falcon.DI +{ + /// + /// 依赖注入实例化工厂 + /// + public interface IFalconDIInstantFactory + { + /// + /// 通过给定容器实例化对象 + /// + T Instance(); + } +} diff --git a/Falcon.DI/IServiceCollectionExtend.cs b/Falcon.DI/IServiceCollectionExtend.cs new file mode 100644 index 0000000..fc0703f --- /dev/null +++ b/Falcon.DI/IServiceCollectionExtend.cs @@ -0,0 +1,48 @@ +using System; +using System.Reflection; +using Microsoft.Extensions.DependencyInjection; +using msdi = Microsoft.Extensions.DependencyInjection; + +namespace Falcon.DI +{ + /// + /// 服务集合方法扩展 + /// + public static class IServiceCollectionExtend + { + /// + /// 实现自动DI注册 + /// + /// 服务集合 + public static IServiceCollection UseFalconDI(this IServiceCollection services,params Assembly[] assemblies) { + if(assemblies == null || assemblies.Length == 0) { + return services.UseFalconDI(AppDomain.CurrentDomain.GetAssemblies()); + } + foreach(Assembly ass in assemblies) { + foreach(Type type in ass.GetTypes()) { + var ra = type.GetCustomAttribute(true); + if(ra != null) { + //如果未提供服务类型,注册到所有实现的接口 + ra.ServiceTypes = ra.ServiceTypes ?? type.GetInterfaces(); + //如果未实现任何接口,注册到类型本身 + if(ra.ServiceTypes == null || ra.ServiceTypes.Length == 0) { + ra.ServiceTypes = new Type[] { type }; + } + foreach(var ser in ra.ServiceTypes) { + services.Add(new ServiceDescriptor(ser,type,convertLifetime(ra.Lifetime))); + } + } + } + } + return services; + } + /// + /// 转换生存期枚举 + /// + /// 生存期 + /// + private static msdi.ServiceLifetime convertLifetime(ServiceLifetime lt) { + return (msdi.ServiceLifetime)(int)lt; + } + } +} diff --git a/Falcon.DI/Properties/PublishProfiles/FolderProfile.pubxml b/Falcon.DI/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..91fcb8f --- /dev/null +++ b/Falcon.DI/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,13 @@ + + + + + FileSystem + Release + Any CPU + netcoreapp2.2 + bin\Debug\netcoreapp2.2\publish\ + + \ No newline at end of file diff --git a/Falcon.DI/ServiceLifetime.cs b/Falcon.DI/ServiceLifetime.cs new file mode 100644 index 0000000..0e8cf4d --- /dev/null +++ b/Falcon.DI/ServiceLifetime.cs @@ -0,0 +1,21 @@ +namespace Falcon.DI +{ + /// + /// 服务生存期 + /// + public enum ServiceLifetime + { + /// + /// 单例 + /// + Singleton = 0, + /// + /// 每个Scoped内单例 + /// + Scoped = 1, + /// + /// 瞬时,每次返回不同的对象 + /// + Transient = 2 + } +} diff --git a/Falcon.ModelSP/DadaContextExtend.cs b/Falcon.ModelSP/DadaContextExtend.cs new file mode 100644 index 0000000..c7640ba --- /dev/null +++ b/Falcon.ModelSP/DadaContextExtend.cs @@ -0,0 +1,125 @@ +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; + + +namespace Falcon.ModelSP +{ + /// + /// 数据库上下文方法扩展 + /// + public static class DataExtend + { + /// + /// 执行无返回值的存储过程 + /// + /// 参数类型 + /// 数据上下文 + /// 参数数据 + public static int RunProcuder(this DbContext db,TPrarmType data) { + var parms = getParams(data); + return db.Database.ExecuteSqlCommand(getProcuderName(),parms.ToArray()); + } + /// + /// 执行有返回值的存储过程 + /// + /// 参数类型 + /// 返回结果项类型 + /// 数据上下文 + /// 参数数据 + public static IEnumerable RunProcuder(this DbContext db,TPrarmType data) + where TResultType : class, new() { + var parms = getParams(data); + return db.Database.SqlQuery(getProcuderName(),parms.ToArray()).ToList(); + } + + /// + /// 获取存储过程参数枚举 + /// + /// 参数模型类型 + /// 参数实例 + private static IEnumerable getParams(T data) { + if(data == null) + yield break; + foreach(var p in typeof(T).GetProperties()) { + if(!p.CanRead || ignoreProp(p)) + continue; + yield return new SqlParameter($"@{getName(p)}",p.GetValue(data)); + } + } + + /// + /// 是否忽略属性 + /// + /// 要检查的属性 + private static bool ignoreProp(PropertyInfo p) { + return p.GetCustomAttribute(true) != null; + } + + /// + /// 获取存储过程参数名称 + /// + /// 对应的属性 + private static string getName(PropertyInfo p) { + var np = p.GetCustomAttribute(true); + if(np != null && np is FalconSPPrarmNameAttribute na) { + return na.Name; + } + return p.Name; + } + /// + /// 获取存储过程名 + /// + /// 参数模型 + private static string getProcuderName() { + var attr = typeof(T).GetCustomAttribute(true); + if(attr != null && attr is FalconSPProcuderNameAttribute pna && !string.IsNullOrEmpty(pna.ProcuderName)) { + return pna.ProcuderName; + } + return typeof(T).Name; + } + + /// + /// 根据传入的sql语句和参数枚举执行存储过程,并且返回类型枚举 + /// + /// 返回值类型 + /// 数据库上下文 + /// 要执行的sql语句 + /// 参数枚举 + /// + public static IEnumerable SqlQuery(this DatabaseFacade db,string sql,params SqlParameter[] paras) + where TR : class, new() { + var connection = db.GetDbConnection(); + using(var cmd = connection.CreateCommand()) { + cmd.CommandText = sql; + cmd.CommandType = System.Data.CommandType.StoredProcedure; + cmd.Parameters.AddRange(paras); + connection.Open(); + var dr = cmd.ExecuteReader(); + var result = new List(); + if(!dr.CanGetColumnSchema()) + return result; + while(dr.Read()) { + var item = new TR(); + var columnSchema = dr.GetColumnSchema(); + for(var i = 0;i < columnSchema.Count;i++) { + var name = dr.GetName(i); + var value = dr.IsDBNull(i) ? null : dr.GetValue(i); + var pi = typeof(TR).GetProperty(name); + if(pi == null || !pi.CanWrite) + continue; + pi.SetValue(item,value); + } + result.Add(item); + } + connection.Close(); + return result; + } + } + + } +} diff --git a/Falcon.ModelSP/Falcon.ModelSP.csproj b/Falcon.ModelSP/Falcon.ModelSP.csproj new file mode 100644 index 0000000..6ab81da --- /dev/null +++ b/Falcon.ModelSP/Falcon.ModelSP.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0;NET461 + + + + + + + + diff --git a/Falcon.ModelSP/FalconSPIgnoreAttribute.cs b/Falcon.ModelSP/FalconSPIgnoreAttribute.cs new file mode 100644 index 0000000..b3bf9e6 --- /dev/null +++ b/Falcon.ModelSP/FalconSPIgnoreAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace Falcon.ModelSP +{ + /// + /// 表示调用时候忽略此属性 + /// + public class FalconSPIgnoreAttribute:Attribute + { + } +} diff --git a/Falcon.ModelSP/FalconSPPrarmNameAttribute.cs b/Falcon.ModelSP/FalconSPPrarmNameAttribute.cs new file mode 100644 index 0000000..8ef4552 --- /dev/null +++ b/Falcon.ModelSP/FalconSPPrarmNameAttribute.cs @@ -0,0 +1,13 @@ +using System; + +namespace Falcon.ModelSP +{ + /// + /// 定义名称 + /// + public class FalconSPPrarmNameAttribute:Attribute + { + public FalconSPPrarmNameAttribute(string name) { this.Name = name; } + public string Name { get; set; } + } +} diff --git a/Falcon.ModelSP/FalconSPProcuderNameAttribute.cs b/Falcon.ModelSP/FalconSPProcuderNameAttribute.cs new file mode 100644 index 0000000..a935c62 --- /dev/null +++ b/Falcon.ModelSP/FalconSPProcuderNameAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace Falcon.ModelSP +{ + /// + /// 定义存储过程名称 + /// + public class FalconSPProcuderNameAttribute:Attribute + { + public string ProcuderName { get; set; } + + public FalconSPProcuderNameAttribute(string m) => this.ProcuderName = m; + } +} diff --git a/Falcon.ModelSP/IFalconSPRuner.cs b/Falcon.ModelSP/IFalconSPRuner.cs new file mode 100644 index 0000000..25b2a96 --- /dev/null +++ b/Falcon.ModelSP/IFalconSPRuner.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; + +namespace Falcon.ModelSP +{ + /// + /// 执行存储过程接口 + /// + public interface IFalconSPRuner + { + /// + /// 通过数据库上下文执行无返回值的存储过程 + /// + /// 参数类型 + /// 数据上下文 + /// 参数数据 + int RunSP(DbContext db,TPrarmType data); + + /// + /// 通过数据库上下文执行存储过程,并返回查询结果 + /// + /// 参数类型 + /// 返回结果项类型 + /// 数据上下文 + /// 参数数据 + IEnumerable RunSP(DbContext db,TPrarmType data) where TResultType : class, new(); + } + + /// + /// 存储过程执行器实现 + /// + public class FalconSPRuner:IFalconSPRuner + { + public int RunSP(DbContext db,TPrarmType data) { + return db.RunProcuder(data); + } + + public IEnumerable RunSP(DbContext db,TPrarmType data) + where TResultType : class, new() { + return db.RunProcuder(data); + } + } +} diff --git a/Falcon.ModelSP/IServiceCollectionExtend.cs b/Falcon.ModelSP/IServiceCollectionExtend.cs new file mode 100644 index 0000000..6ea9f7d --- /dev/null +++ b/Falcon.ModelSP/IServiceCollectionExtend.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Extensions.DependencyInjection; + +namespace Falcon.ModelSP +{ + /// + /// IServiceCollection扩展 + /// + public static class IServiceCollectionExtend + { + /// + /// 注册对数据库存储过程模型化的调用扩展 + /// + /// 注册服务集合 + /// + public static IServiceCollection UseFalconSP(this IServiceCollection services) { + return services.AddSingleton(); + } + } +} diff --git a/Falcon.ModelSP/ProcuderNotFoundException.cs b/Falcon.ModelSP/ProcuderNotFoundException.cs new file mode 100644 index 0000000..d785eb4 --- /dev/null +++ b/Falcon.ModelSP/ProcuderNotFoundException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Falcon.ModelSP +{ + /// + /// 存储过程没有找到的异常 + /// + public class ProcuderNotFoundException:Exception + { + public ProcuderNotFoundException() : base("存储过程没有找到") { } + } +} diff --git a/FalconCore.sln b/FalconCore.sln new file mode 100644 index 0000000..59f55c5 --- /dev/null +++ b/FalconCore.sln @@ -0,0 +1,67 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29201.188 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.DI", "Falcon.DI\Falcon.DI.csproj", "{C32977BC-428C-4249-B115-0AE2A06149E5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.DI.Test", "Falcon.DI.Test\Falcon.DI.Test.csproj", "{35BAAEAB-46D0-4265-8633-EB8063F769CF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.Cache", "Falcon.Cache\Falcon.Cache.csproj", "{1B081C80-C3BF-4F78-A9AA-FF2E8A9EC627}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MS.ResidCache.Test", "MS.ResidCache.Test\MS.ResidCache.Test.csproj", "{9572943D-9960-4FAD-81F5-B2EBF9FE7338}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.Packget.Test", "Falcon.DI.Packget.Test\Falcon.Packget.Test.csproj", "{2BFA3AC6-5A87-4B2A-8487-AAE62A41FDE4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.ModelSP", "Falcon.ModelSP\Falcon.ModelSP.csproj", "{D31D628F-60F5-4F98-8280-2D312B0A99F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Falcon.AutoTableLog", "Falcon.AutoTableLog\Falcon.AutoTableLog.csproj", "{61C50690-4419-4F6D-B34D-4258565185E9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Falcon.AutoTableLog.Test", "Falcon.AutoTableLog.Test\Falcon.AutoTableLog.Test.csproj", "{D60683D5-D6F6-41EE-9627-43C34C977C45}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C32977BC-428C-4249-B115-0AE2A06149E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C32977BC-428C-4249-B115-0AE2A06149E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C32977BC-428C-4249-B115-0AE2A06149E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C32977BC-428C-4249-B115-0AE2A06149E5}.Release|Any CPU.Build.0 = Release|Any CPU + {35BAAEAB-46D0-4265-8633-EB8063F769CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35BAAEAB-46D0-4265-8633-EB8063F769CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35BAAEAB-46D0-4265-8633-EB8063F769CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35BAAEAB-46D0-4265-8633-EB8063F769CF}.Release|Any CPU.Build.0 = Release|Any CPU + {1B081C80-C3BF-4F78-A9AA-FF2E8A9EC627}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B081C80-C3BF-4F78-A9AA-FF2E8A9EC627}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B081C80-C3BF-4F78-A9AA-FF2E8A9EC627}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B081C80-C3BF-4F78-A9AA-FF2E8A9EC627}.Release|Any CPU.Build.0 = Release|Any CPU + {9572943D-9960-4FAD-81F5-B2EBF9FE7338}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9572943D-9960-4FAD-81F5-B2EBF9FE7338}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9572943D-9960-4FAD-81F5-B2EBF9FE7338}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9572943D-9960-4FAD-81F5-B2EBF9FE7338}.Release|Any CPU.Build.0 = Release|Any CPU + {2BFA3AC6-5A87-4B2A-8487-AAE62A41FDE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BFA3AC6-5A87-4B2A-8487-AAE62A41FDE4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BFA3AC6-5A87-4B2A-8487-AAE62A41FDE4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BFA3AC6-5A87-4B2A-8487-AAE62A41FDE4}.Release|Any CPU.Build.0 = Release|Any CPU + {D31D628F-60F5-4F98-8280-2D312B0A99F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D31D628F-60F5-4F98-8280-2D312B0A99F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D31D628F-60F5-4F98-8280-2D312B0A99F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D31D628F-60F5-4F98-8280-2D312B0A99F1}.Release|Any CPU.Build.0 = Release|Any CPU + {61C50690-4419-4F6D-B34D-4258565185E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61C50690-4419-4F6D-B34D-4258565185E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61C50690-4419-4F6D-B34D-4258565185E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61C50690-4419-4F6D-B34D-4258565185E9}.Release|Any CPU.Build.0 = Release|Any CPU + {D60683D5-D6F6-41EE-9627-43C34C977C45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D60683D5-D6F6-41EE-9627-43C34C977C45}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D60683D5-D6F6-41EE-9627-43C34C977C45}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D60683D5-D6F6-41EE-9627-43C34C977C45}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {ED64939B-E078-43FD-B716-81EFE00AB638} + EndGlobalSection +EndGlobal diff --git a/MS.ResidCache.Test/MS.ResidCache.Test.csproj b/MS.ResidCache.Test/MS.ResidCache.Test.csproj new file mode 100644 index 0000000..06f01d1 --- /dev/null +++ b/MS.ResidCache.Test/MS.ResidCache.Test.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.2 + + false + + + + + + + + + + + diff --git a/MS.ResidCache.Test/MS_MemeryCacheUnitTest.cs b/MS.ResidCache.Test/MS_MemeryCacheUnitTest.cs new file mode 100644 index 0000000..9e6c142 --- /dev/null +++ b/MS.ResidCache.Test/MS_MemeryCacheUnitTest.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Design; +using System.Text; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace MS.ResidCache.Test +{ + [TestClass] + public class MS_MemeryCacheUnitTest + { + [TestMethod] + public void IDistributedCacheTestMethod() { + + IMemoryCache cache = new MemoryCache(new MemoryCacheOptions { + + }); + var key = "mcut_a"; + cache.Set(key,key); + var r = cache.Get(key); + Assert.AreEqual(r,key); + cache.Remove(key); + r = cache.Get(key); + Assert.IsNull(r); + + if(cache is MemoryCache dis) { + dis.Dispose(); + } + } + } +} diff --git a/MS.ResidCache.Test/MicrosoftRedisCacheUnitTest.cs b/MS.ResidCache.Test/MicrosoftRedisCacheUnitTest.cs new file mode 100644 index 0000000..a4935ad --- /dev/null +++ b/MS.ResidCache.Test/MicrosoftRedisCacheUnitTest.cs @@ -0,0 +1,29 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.Extensions.Caching.Redis; +using Microsoft.Extensions.Caching.Distributed; + +namespace MS.ResidCache.Test +{ + [TestClass] + public class MicrosoftRedisCacheUnitTest + { + [TestMethod] + public void IDistributedCacheTestMethod1() { + IDistributedCache cache = new RedisCache(new RedisCacheOptions { + Configuration = "127.0.0.1:7001,password=123654", + InstanceName = "mcut", + }); + var key = "mcut_a"; + cache.SetString(key,key); + var r = cache.GetString(key); + Assert.AreEqual(r,key); + cache.Remove(key); + r = cache.GetString(key); + Assert.IsNull(r); + + if(cache is RedisCache dis) { + dis.Dispose(); + } + } + } +}