Selaa lähdekoodia

新增对象动态增删属性

懒得勤快 6 vuotta sitten
vanhempi
sitoutus
fbc1d18c10

+ 1 - 1
Masuit.Tools.Core/Masuit.Tools.Core.csproj

@@ -2,7 +2,7 @@
 
 
   <PropertyGroup>
   <PropertyGroup>
     <TargetFramework>netcoreapp2.1</TargetFramework>
     <TargetFramework>netcoreapp2.1</TargetFramework>
-    <Version>2.2</Version>
+    <Version>2.2.1</Version>
     <Authors>懒得勤快</Authors>
     <Authors>懒得勤快</Authors>
     <Company>masuit.com</Company>
     <Company>masuit.com</Company>
     <Description>包含一些常用的操作类,大都是静态类,加密解密,反射操作,硬件信息,字符串扩展方法,日期时间扩展操作,大文件拷贝,图像裁剪,html处理,验证码、NoSql等常用封装。
     <Description>包含一些常用的操作类,大都是静态类,加密解密,反射操作,硬件信息,字符串扩展方法,日期时间扩展操作,大文件拷贝,图像裁剪,html处理,验证码、NoSql等常用封装。

+ 69 - 69
Masuit.Tools.Core/Net/MultiThreadDownloader.cs

@@ -21,6 +21,75 @@ namespace Masuit.Tools.Net
     /// </summary>
     /// </summary>
     public class MultiThreadDownloader
     public class MultiThreadDownloader
     {
     {
+        #region 属性
+
+        private string _url;
+        private bool _rangeAllowed;
+
+        #endregion
+
+        #region 公共属性
+
+        /// <summary>
+        /// RangeAllowed
+        /// </summary>
+        public bool RangeAllowed
+        {
+            get => _rangeAllowed;
+            set => _rangeAllowed = value;
+        }
+
+        /// <summary>
+        /// 临时文件夹
+        /// </summary>
+        public string TempFileDirectory { get; set; }
+
+        /// <summary>
+        /// url地址
+        /// </summary>
+        public string Url
+        {
+            get => _url;
+            set => _url = value;
+        }
+
+        /// <summary>
+        /// 第几部分
+        /// </summary>
+        public int NumberOfParts { get; set; }
+
+        /// <summary>
+        /// 已接收字节数
+        /// </summary>
+        public long TotalBytesReceived => PartialDownloaderList.Where(t => t != null).Sum(t => t.TotalBytesRead);
+
+        /// <summary>
+        /// 总进度
+        /// </summary>
+        public float TotalProgress { get; private set; }
+
+        /// <summary>
+        /// 文件大小
+        /// </summary>
+        public long Size { get; private set; }
+
+        /// <summary>
+        /// 下载速度
+        /// </summary>
+        public float TotalSpeedInBytes => PartialDownloaderList.Sum(t => t.SpeedInBytes);
+
+        /// <summary>
+        /// 下载块
+        /// </summary>
+        public List<PartialDownloader> PartialDownloaderList { get; }
+
+        /// <summary>
+        /// 文件路径
+        /// </summary>
+        public string FilePath { get; set; }
+
+        #endregion
+
         #region 变量
         #region 变量
 
 
         /// <summary>
         /// <summary>
@@ -342,74 +411,5 @@ namespace Masuit.Tools.Net
         }
         }
 
 
         #endregion
         #endregion
-
-        #region 属性
-
-        private string _url;
-        private bool _rangeAllowed;
-
-        #endregion
-
-        #region 公共属性
-
-        /// <summary>
-        /// RangeAllowed
-        /// </summary>
-        public bool RangeAllowed
-        {
-            get => _rangeAllowed;
-            set => _rangeAllowed = value;
-        }
-
-        /// <summary>
-        /// 临时文件夹
-        /// </summary>
-        public string TempFileDirectory { get; set; }
-
-        /// <summary>
-        /// url地址
-        /// </summary>
-        public string Url
-        {
-            get => _url;
-            set => _url = value;
-        }
-
-        /// <summary>
-        /// 第几部分
-        /// </summary>
-        public int NumberOfParts { get; set; }
-
-        /// <summary>
-        /// 已接收字节数
-        /// </summary>
-        public long TotalBytesReceived => PartialDownloaderList.Where(t => t != null).Sum(t => t.TotalBytesRead);
-
-        /// <summary>
-        /// 总进度
-        /// </summary>
-        public int TotalProgress { get; private set; }
-
-        /// <summary>
-        /// 文件大小
-        /// </summary>
-        public long Size { get; private set; }
-
-        /// <summary>
-        /// 下载速度
-        /// </summary>
-        public int TotalSpeedInBytes => PartialDownloaderList.Sum(t => t.SpeedInBytes);
-
-        /// <summary>
-        /// 下载块
-        /// </summary>
-        public List<PartialDownloader> PartialDownloaderList { get; }
-
-        /// <summary>
-        /// 文件路径
-        /// </summary>
-        public string FilePath { get; set; }
-
-        #endregion
     }
     }
 }
 }

+ 451 - 0
Masuit.Tools.Core/Reflection/ClassHelper.cs

@@ -0,0 +1,451 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Masuit.Tools.Reflection
+{
+    /// <summary>  
+    /// 类帮助器,可以动态对类,类成员进行控制(添加,删除),目前只支持属性控制。  
+    /// 注意,属性以外的其它成员会被清空,功能还有待完善,使其不影响其它成员。  
+    /// </summary>  
+    public static class ClassHelper
+    {
+        #region 公有方法  
+
+        /// <summary>  
+        /// 根据类的类型型创建类实例。  
+        /// </summary>  
+        /// <param name="t">将要创建的类型。</param>  
+        /// <returns>返回创建的类实例。</returns>  
+        public static object CreateInstance(this Type t)
+        {
+            return Activator.CreateInstance(t);
+        }
+
+
+        /// <summary>  
+        /// 根据类的名称,属性列表创建型实例。  
+        /// </summary>  
+        /// <param name="className">将要创建的类的名称。</param>  
+        /// <param name="lcpi">将要创建的类的属性列表。</param>  
+        /// <returns>返回创建的类实例</returns>  
+        public static object CreateInstance(string className, List<CustPropertyInfo> lcpi)
+        {
+            return Activator.CreateInstance(AddProperty(BuildType(className), lcpi));
+        }
+
+
+        /// <summary>  
+        /// 根据属性列表创建类的实例,默认类名为DefaultClass,由于生成的类不是强类型,所以类名可以忽略。  
+        /// </summary>  
+        /// <param name="lcpi">将要创建的类的属性列表</param>  
+        /// <returns>返回创建的类的实例。</returns>  
+        public static object CreateInstance(List<CustPropertyInfo> lcpi)
+        {
+            return CreateInstance("DefaultClass", lcpi);
+        }
+
+        /// <summary>  
+        /// 创建一个没有成员的类型的实例,类名为"DefaultClass"。  
+        /// </summary>  
+        /// <returns>返回创建的类型的实例。</returns>  
+        public static Type BuildType()
+        {
+            return BuildType("DefaultClass");
+        }
+
+
+        /// <summary>  
+        /// 根据类名创建一个没有成员的类型的实例。  
+        /// </summary>  
+        /// <param name="className">将要创建的类型的实例的类名。</param>  
+        /// <returns>返回创建的类型的实例。</returns>  
+        public static Type BuildType(string className)
+        {
+            AssemblyName myAsmName = new AssemblyName
+            {
+                Name = "MyDynamicAssembly"
+            };
+
+            //创建一个永久程序集,设置为AssemblyBuilderAccess.RunAndSave。  
+            AssemblyBuilder myAsmBuilder = AssemblyBuilder.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndCollect);
+
+            //创建一个永久单模程序块。  
+            ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name);
+            //创建TypeBuilder。  
+            TypeBuilder myTypeBuilder = myModBuilder.DefineType(className, TypeAttributes.Public);
+
+            //创建类型。  
+            Type retval = myTypeBuilder.CreateType();
+
+            //保存程序集,以便可以被Ildasm.exe解析,或被测试程序引用。  
+            //myAsmBuilder.Save(myAsmName.Name + ".dll");  
+            return retval;
+        }
+
+        ///<summary>  
+        /// 添加属性到类型的实例,注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="classType">指定类型的实例。</param>  
+        /// <param name="lcpi">表示属性的一个列表。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type AddProperty(this Type classType, List<CustPropertyInfo> lcpi)
+        {
+            //合并先前的属性,以便一起在下一步进行处理。  
+            MergeProperty(classType, lcpi);
+            //把属性加入到Type。  
+            return AddPropertyToType(classType, lcpi);
+        }
+
+
+        /// <summary>  
+        /// 添加属性到类型的实例,注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="classType">指定类型的实例。</param>  
+        /// <param name="cpi">表示一个属性。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type AddProperty(this Type classType, CustPropertyInfo cpi)
+        {
+            List<CustPropertyInfo> lcpi = new List<CustPropertyInfo>
+            {
+                cpi
+            };
+            //合并先前的属性,以便一起在下一步进行处理。  
+            MergeProperty(classType, lcpi);
+            //把属性加入到Type。  
+            return AddPropertyToType(classType, lcpi);
+        }
+
+        /// <summary>
+        /// 给对象实例添加新属性并返回新对象实例
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="lcpi">自定义属性对象集合</param>
+        /// <returns></returns>
+        public static object AddProperty(this object obj, List<CustPropertyInfo> lcpi)
+        {
+            Type originType = obj.GetType();
+            var customs = lcpi.ToDictionary(i => i.PropertyName, i => i.PropertyValue);
+            var dest = AddProperty(originType, lcpi).CreateInstance();
+            foreach (var originProperty in originType.GetProperties())
+            {
+                dest.SetProperty(originProperty.Name, originProperty.GetValue(obj));
+            }
+
+            foreach (var cpi in customs)
+            {
+                dest.SetProperty(cpi.Key, cpi.Value);
+            }
+
+            return dest;
+        }
+
+        /// <summary>
+        /// 给对象实例添加新属性并返回新对象实例
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="cpi">自定义属性对象</param>
+        /// <returns></returns>
+        public static object AddProperty(this object obj, CustPropertyInfo cpi)
+        {
+            return AddProperty(obj, new List<CustPropertyInfo>()
+            {
+                cpi
+            });
+        }
+
+        /// <summary>  
+        /// 从类型的实例中移除属性,注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="classType">指定类型的实例。</param>  
+        /// <param name="propertyName">要移除的属性。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type DeleteProperty(this Type classType, string propertyName)
+        {
+            List<string> ls = new List<string>
+            {
+                propertyName
+            };
+
+            //合并先前的属性,以便一起在下一步进行处理。  
+            List<CustPropertyInfo> lcpi = SeparateProperty(classType, ls);
+            //把属性加入到Type。  
+            return AddPropertyToType(classType, lcpi);
+        }
+
+
+        /// <summary>  
+        /// 从类型的实例中移除属性,注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="classType">指定类型的实例。</param>  
+        /// <param name="propertyNames">要移除的属性列表。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type DeleteProperty(this Type classType, List<string> propertyNames)
+        {
+            //合并先前的属性,以便一起在下一步进行处理。  
+            List<CustPropertyInfo> lcpi = SeparateProperty(classType, propertyNames);
+            //把属性加入到Type。  
+            return AddPropertyToType(classType, lcpi);
+        }
+
+        /// <summary>
+        /// 删除对象的属性并返回新对象实例
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="propertyNames">属性名集合</param>
+        /// <returns></returns>
+        public static object DeleteProperty(this object obj, List<string> propertyNames)
+        {
+            PropertyInfo[] oldProperties = obj.GetType().GetProperties();
+            Type t = obj.GetType();
+            foreach (string p in propertyNames)
+            {
+                t = t.DeleteProperty(p);
+            }
+
+            var newInstance = t.CreateInstance();
+            foreach (var p in newInstance.GetProperties())
+            {
+                newInstance.SetProperty(p.Name, oldProperties.FirstOrDefault(i => i.Name.Equals(p.Name)).GetValue(obj));
+            }
+
+            return newInstance;
+        }
+
+        /// <summary>
+        /// 删除对象的属性并返回新对象实例
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="property">属性名</param>
+        /// <returns></returns>
+        public static object DeleteProperty(this object obj, string property)
+        {
+            return DeleteProperty(obj, new List<string>()
+            {
+                property
+            });
+        }
+
+        #endregion
+
+        #region 私有方法  
+
+        /// <summary>  
+        /// 把类型的实例t和lcpi参数里的属性进行合并。  
+        /// </summary>  
+        /// <param name="t">实例t</param>  
+        /// <param name="lcpi">里面包含属性列表的信息。</param>  
+        private static void MergeProperty(Type t, List<CustPropertyInfo> lcpi)
+        {
+            foreach (PropertyInfo pi in t.GetProperties())
+            {
+                CustPropertyInfo cpi = new CustPropertyInfo(pi.PropertyType, pi.Name);
+                lcpi.Add(cpi);
+            }
+        }
+
+
+        /// <summary>  
+        /// 从类型的实例t的属性移除属性列表lcpi,返回的新属性列表在lcpi中。  
+        /// </summary>  
+        /// <param name="t">类型的实例t。</param>  
+        /// <param name="ls">要移除的属性列表。</param>  
+        private static List<CustPropertyInfo> SeparateProperty(Type t, List<string> ls)
+        {
+            List<CustPropertyInfo> ret = new List<CustPropertyInfo>();
+            foreach (PropertyInfo pi in t.GetProperties())
+            {
+                foreach (string s in ls)
+                {
+                    if (pi.Name != s)
+                    {
+                        CustPropertyInfo cpi = new CustPropertyInfo(pi.PropertyType, pi.Name);
+                        ret.Add(cpi);
+                    }
+                }
+            }
+
+            return ret;
+        }
+
+
+        /// <summary>  
+        /// 把lcpi参数里的属性加入到myTypeBuilder中。注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="myTypeBuilder">类型构造器的实例。</param>  
+        /// <param name="lcpi">里面包含属性列表的信息。</param>  
+        private static void AddPropertyToTypeBuilder(TypeBuilder myTypeBuilder, List<CustPropertyInfo> lcpi)
+        {
+            // 属性Set和Get方法要一个专门的属性。这里设置为Public。  
+            var getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
+
+            // 添加属性到myTypeBuilder。  
+            foreach (CustPropertyInfo cpi in lcpi)
+            {
+                //定义字段。  
+                FieldBuilder customerNameBldr = myTypeBuilder.DefineField(cpi.FieldName, cpi.Type, FieldAttributes.Private);
+                //customerNameBldr.SetConstant("11111111");
+                //定义属性。  
+                //最后一个参数为null,因为属性没有参数。  
+                var custNamePropBldr = myTypeBuilder.DefineProperty(cpi.PropertyName, PropertyAttributes.HasDefault, cpi.Type, null);
+
+                //custNamePropBldr.SetConstant("111111111");
+                //定义Get方法。  
+                var custNameGetPropMthdBldr = myTypeBuilder.DefineMethod(cpi.GetPropertyMethodName, getSetAttr, cpi.Type, Type.EmptyTypes);
+
+                var custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();
+
+                try
+                {
+                    custNameGetIL.Emit(OpCodes.Ldarg_0);
+                    //custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);  
+                    custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);
+                    custNameGetIL.Emit(OpCodes.Ret);
+                }
+                catch (Exception)
+                {
+                    // ignored
+                }
+
+                //定义Set方法。  
+                var custNameSetPropMthdBldr = myTypeBuilder.DefineMethod(cpi.SetPropertyMethodName, getSetAttr, null, new[]
+                {
+                    cpi.Type
+                });
+
+                var custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();
+
+                custNameSetIL.Emit(OpCodes.Ldarg_0);
+                custNameSetIL.Emit(OpCodes.Ldarg_1);
+                custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);
+                custNameSetIL.Emit(OpCodes.Ret);
+                //custNamePropBldr.SetConstant("ceshi");  
+                //把创建的两个方法(Get,Set)加入到PropertyBuilder中。  
+                custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
+                custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);
+            }
+        }
+
+
+        /// <summary>  
+        /// 把属性加入到类型的实例。  
+        /// </summary>  
+        /// <param name="classType">类型的实例。</param>  
+        /// <param name="lcpi">要加入的属性列表。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type AddPropertyToType(this Type classType, List<CustPropertyInfo> lcpi)
+        {
+            AssemblyName myAsmName = new AssemblyName
+            {
+                Name = "MyDynamicAssembly"
+            };
+
+            //创建一个永久程序集,设置为AssemblyBuilderAccess.RunAndCollect。  
+            AssemblyBuilder myAsmBuilder = AssemblyBuilder.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndCollect);
+
+            //创建一个永久单模程序块。  
+            ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name);
+            //创建TypeBuilder。  
+            // ReSharper disable once AssignNullToNotNullAttribute
+            TypeBuilder myTypeBuilder = myModBuilder.DefineType(classType.FullName, TypeAttributes.Public);
+
+            //把lcpi中定义的属性加入到TypeBuilder。将清空其它的成员。其功能有待扩展,使其不影响其它成员。  
+            AddPropertyToTypeBuilder(myTypeBuilder, lcpi);
+
+            //创建类型。  
+            Type retval = myTypeBuilder.CreateType();
+
+            //保存程序集,以便可以被Ildasm.exe解析,或被测试程序引用。  
+            //myAsmBuilder.Save(myAsmName.Name + ".dll");  
+            return retval;
+        }
+
+        #endregion
+
+        #region 辅助类  
+
+        /// <summary>  
+        /// 自定义的属性信息类型。  
+        /// </summary>  
+        public class CustPropertyInfo
+        {
+            /// <summary>  
+            /// 空构造。  
+            /// </summary>  
+            public CustPropertyInfo()
+            {
+            }
+
+            /// <summary>  
+            /// 根据属性类型名称,属性名称构造实例。  
+            /// </summary>  
+            /// <param name="type">属性类型名称。</param>  
+            /// <param name="propertyName">属性名称。</param>  
+            public CustPropertyInfo(Type type, string propertyName)
+            {
+                Type = type;
+                PropertyName = propertyName;
+            }
+
+            public CustPropertyInfo(Type type, string propertyName, object propertyValue) : this(type, propertyName)
+            {
+                PropertyValue = propertyValue;
+            }
+
+            /// <summary>  
+            /// 获取或设置属性类型名称。  
+            /// </summary>  
+            public Type Type { get; set; }
+
+            /// <summary>  
+            /// 获取或设置属性名称。  
+            /// </summary>  
+            public string PropertyName { get; set; }
+
+            /// <summary>
+            /// 属性值
+            /// </summary>
+            public object PropertyValue { get; set; }
+
+            /// <summary>  
+            /// 获取属性字段名称。  
+            /// </summary>  
+            public string FieldName
+            {
+                get
+                {
+                    if (PropertyName.Length < 1)
+                    {
+                        return "";
+                    }
+
+                    return PropertyName.Substring(0, 1).ToLower() + PropertyName.Substring(1);
+                }
+            }
+
+            /// <summary>  
+            /// 获取属性在IL中的Set方法名。  
+            /// </summary>  
+            public string SetPropertyMethodName => "set_" + PropertyName;
+
+
+            /// <summary>  
+            ///  获取属性在IL中的Get方法名。  
+            /// </summary>  
+            public string GetPropertyMethodName => "get_" + PropertyName;
+        }
+
+        #endregion
+    }
+
+    [Serializable]
+    internal enum StackCrawlMark
+    {
+        LookForMe,
+        LookForMyCaller,
+        LookForMyCallersCaller,
+        LookForThread,
+    }
+}

+ 52 - 0
Masuit.Tools.UnitTest/ClassHelperTest.cs

@@ -0,0 +1,52 @@
+using Masuit.Tools.Reflection;
+using System.Collections.Generic;
+using Xunit;
+
+namespace Masuit.Tools.UnitTest
+{
+    public class ClassHelperTest
+    {
+        [Fact]
+        public void Can_AddProperty_ReturnNewInstance()
+        {
+            // arrange
+            MyClass myClass = new MyClass();
+
+            // act
+            dynamic newObj = myClass.AddProperty(new List<ClassHelper.CustPropertyInfo>()
+            {
+                new ClassHelper.CustPropertyInfo(typeof(string),"Name","张三"),
+                new ClassHelper.CustPropertyInfo(typeof(int),"Age",20),
+            });
+
+            // act
+            Assert.Equal("张三", newObj.Name);
+            Assert.Equal(20, newObj.Age);
+        }
+
+        [Fact]
+        public void Can_RemoveProperty_ReturnNewInstance()
+        {
+            // arrange
+            MyClass myClass = new MyClass()
+            {
+                MyProperty = "aa",
+                Number = 123
+            };
+
+            // act
+            object newObj = myClass.DeleteProperty("MyProperty");
+
+            // act
+            int propertyCount = newObj.GetType().GetProperties().Length;
+            Assert.Equal(1, propertyCount);
+        }
+    }
+
+    public class MyClass
+    {
+        public string MyProperty { get; set; }
+        public int Number { get; set; }
+
+    }
+}

+ 2 - 0
Masuit.Tools.UnitTest/Masuit.Tools.UnitTest.csproj

@@ -44,6 +44,7 @@
     <Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
     <Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
       <HintPath>..\packages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll</HintPath>
       <HintPath>..\packages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll</HintPath>
     </Reference>
     </Reference>
+    <Reference Include="Microsoft.CSharp" />
     <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
     <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
       <HintPath>..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
     </Reference>
     </Reference>
@@ -103,6 +104,7 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Compile Include="ChineseCalendarTest.cs" />
     <Compile Include="ChineseCalendarTest.cs" />
+    <Compile Include="ClassHelperTest.cs" />
     <Compile Include="ExtensionMethodsTest.cs" />
     <Compile Include="ExtensionMethodsTest.cs" />
     <Compile Include="HtmlToolsTest.cs" />
     <Compile Include="HtmlToolsTest.cs" />
     <Compile Include="LinqExtensionTest.cs" />
     <Compile Include="LinqExtensionTest.cs" />

+ 1 - 0
Masuit.Tools/Masuit.Tools.csproj

@@ -137,6 +137,7 @@
     <Compile Include="Net\PartialDownloader.cs" />
     <Compile Include="Net\PartialDownloader.cs" />
     <Compile Include="Net\SocketClient.cs" />
     <Compile Include="Net\SocketClient.cs" />
     <Compile Include="NoSQL\RedisHelper.cs" />
     <Compile Include="NoSQL\RedisHelper.cs" />
+    <Compile Include="Reflection\ClassHelper.cs" />
     <Compile Include="Reflection\ReflectHelper.cs" />
     <Compile Include="Reflection\ReflectHelper.cs" />
     <Compile Include="Reflection\ReflectionUtil.cs" />
     <Compile Include="Reflection\ReflectionUtil.cs" />
     <Compile Include="Security\Encrypt.cs" />
     <Compile Include="Security\Encrypt.cs" />

+ 69 - 69
Masuit.Tools/Net/MultiThreadDownloader.cs

@@ -21,6 +21,75 @@ namespace Masuit.Tools.Net
     /// </summary>
     /// </summary>
     public class MultiThreadDownloader
     public class MultiThreadDownloader
     {
     {
+        #region 属性
+
+        private string _url;
+        private bool _rangeAllowed;
+
+        #endregion
+
+        #region 公共属性
+
+        /// <summary>
+        /// RangeAllowed
+        /// </summary>
+        public bool RangeAllowed
+        {
+            get => _rangeAllowed;
+            set => _rangeAllowed = value;
+        }
+
+        /// <summary>
+        /// 临时文件夹
+        /// </summary>
+        public string TempFileDirectory { get; set; }
+
+        /// <summary>
+        /// url地址
+        /// </summary>
+        public string Url
+        {
+            get => _url;
+            set => _url = value;
+        }
+
+        /// <summary>
+        /// 第几部分
+        /// </summary>
+        public int NumberOfParts { get; set; }
+
+        /// <summary>
+        /// 已接收字节数
+        /// </summary>
+        public long TotalBytesReceived => PartialDownloaderList.Where(t => t != null).Sum(t => t.TotalBytesRead);
+
+        /// <summary>
+        /// 总进度
+        /// </summary>
+        public float TotalProgress { get; private set; }
+
+        /// <summary>
+        /// 文件大小
+        /// </summary>
+        public long Size { get; private set; }
+
+        /// <summary>
+        /// 下载速度
+        /// </summary>
+        public float TotalSpeedInBytes => PartialDownloaderList.Sum(t => t.SpeedInBytes);
+
+        /// <summary>
+        /// 下载块
+        /// </summary>
+        public List<PartialDownloader> PartialDownloaderList { get; }
+
+        /// <summary>
+        /// 文件路径
+        /// </summary>
+        public string FilePath { get; set; }
+
+        #endregion
+
         #region 变量
         #region 变量
 
 
         /// <summary>
         /// <summary>
@@ -342,74 +411,5 @@ namespace Masuit.Tools.Net
         }
         }
 
 
         #endregion
         #endregion
-
-        #region 属性
-
-        private string _url;
-        private bool _rangeAllowed;
-
-        #endregion
-
-        #region 公共属性
-
-        /// <summary>
-        /// RangeAllowed
-        /// </summary>
-        public bool RangeAllowed
-        {
-            get => _rangeAllowed;
-            set => _rangeAllowed = value;
-        }
-
-        /// <summary>
-        /// 临时文件夹
-        /// </summary>
-        public string TempFileDirectory { get; set; }
-
-        /// <summary>
-        /// url地址
-        /// </summary>
-        public string Url
-        {
-            get => _url;
-            set => _url = value;
-        }
-
-        /// <summary>
-        /// 第几部分
-        /// </summary>
-        public int NumberOfParts { get; set; }
-
-        /// <summary>
-        /// 已接收字节数
-        /// </summary>
-        public long TotalBytesReceived => PartialDownloaderList.Where(t => t != null).Sum(t => t.TotalBytesRead);
-
-        /// <summary>
-        /// 总进度
-        /// </summary>
-        public int TotalProgress { get; private set; }
-
-        /// <summary>
-        /// 文件大小
-        /// </summary>
-        public long Size { get; private set; }
-
-        /// <summary>
-        /// 下载速度
-        /// </summary>
-        public int TotalSpeedInBytes => PartialDownloaderList.Sum(t => t.SpeedInBytes);
-
-        /// <summary>
-        /// 下载块
-        /// </summary>
-        public List<PartialDownloader> PartialDownloaderList { get; }
-
-        /// <summary>
-        /// 文件路径
-        /// </summary>
-        public string FilePath { get; set; }
-
-        #endregion
     }
     }
 }
 }

+ 1 - 1
Masuit.Tools/Properties/AssemblyInfo.cs

@@ -36,7 +36,7 @@ using System.Runtime.InteropServices;
 // 方法是按如下所示使用“*”: :
 // 方法是按如下所示使用“*”: :
 // [assembly: AssemblyVersion("1.0.*")]
 // [assembly: AssemblyVersion("1.0.*")]
 
 
-[assembly: AssemblyVersion("2.2.0.0")]
+[assembly: AssemblyVersion("2.2.1.0")]
 [assembly: AssemblyFileVersion("2.2.0.0")]
 [assembly: AssemblyFileVersion("2.2.0.0")]
 [assembly: NeutralResourcesLanguage("zh-CN")]
 [assembly: NeutralResourcesLanguage("zh-CN")]
 
 

+ 432 - 0
Masuit.Tools/Reflection/ClassHelper.cs

@@ -0,0 +1,432 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace Masuit.Tools.Reflection
+{
+    /// <summary>  
+    /// 类帮助器,可以动态对类,类成员进行控制(添加,删除),目前只支持属性控制。  
+    /// 注意,属性以外的其它成员会被清空,功能还有待完善,使其不影响其它成员。  
+    /// </summary>  
+    public static class ClassHelper
+    {
+        #region 公有方法  
+
+        /// <summary>  
+        /// 根据类的类型型创建类实例。  
+        /// </summary>  
+        /// <param name="t">将要创建的类型。</param>  
+        /// <returns>返回创建的类实例。</returns>  
+        public static object CreateInstance(this Type t)
+        {
+            return Activator.CreateInstance(t);
+        }
+
+
+        /// <summary>  
+        /// 根据类的名称,属性列表创建型实例。  
+        /// </summary>  
+        /// <param name="className">将要创建的类的名称。</param>  
+        /// <param name="lcpi">将要创建的类的属性列表。</param>  
+        /// <returns>返回创建的类实例</returns>  
+        public static object CreateInstance(string className, List<CustPropertyInfo> lcpi)
+        {
+            return Activator.CreateInstance(AddProperty(BuildType(className), lcpi));
+        }
+
+
+        /// <summary>  
+        /// 根据属性列表创建类的实例,默认类名为DefaultClass,由于生成的类不是强类型,所以类名可以忽略。  
+        /// </summary>  
+        /// <param name="lcpi">将要创建的类的属性列表</param>  
+        /// <returns>返回创建的类的实例。</returns>  
+        public static object CreateInstance(List<CustPropertyInfo> lcpi)
+        {
+            return CreateInstance("DefaultClass", lcpi);
+        }
+
+        /// <summary>  
+        /// 创建一个没有成员的类型的实例,类名为"DefaultClass"。  
+        /// </summary>  
+        /// <returns>返回创建的类型的实例。</returns>  
+        public static Type BuildType()
+        {
+            return BuildType("DefaultClass");
+        }
+
+
+        /// <summary>  
+        /// 根据类名创建一个没有成员的类型的实例。  
+        /// </summary>  
+        /// <param name="className">将要创建的类型的实例的类名。</param>  
+        /// <returns>返回创建的类型的实例。</returns>  
+        public static Type BuildType(string className)
+        {
+            AssemblyName myAsmName = new AssemblyName
+            {
+                Name = "MyDynamicAssembly"
+            };
+
+            //创建一个程序集,设置为AssemblyBuilderAccess.RunAndCollect。  
+            AssemblyBuilder myAsmBuilder = AssemblyBuilder.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndCollect);
+
+            //创建一个单模程序块。  
+            ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name);
+            //创建TypeBuilder。  
+            TypeBuilder myTypeBuilder = myModBuilder.DefineType(className, TypeAttributes.Public);
+
+            //创建类型。  
+            Type retval = myTypeBuilder.CreateType();
+
+            //保存程序集,以便可以被Ildasm.exe解析,或被测试程序引用。  
+            //myAsmBuilder.Save(myAsmName.Name + ".dll");  
+            return retval;
+        }
+
+
+        /// <summary>  
+        /// 添加属性到类型的实例,注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="classType">指定类型的实例。</param>  
+        /// <param name="lcpi">表示属性的一个列表。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type AddProperty(this Type classType, List<CustPropertyInfo> lcpi)
+        {
+            //合并先前的属性,以便一起在下一步进行处理。  
+            MergeProperty(classType, lcpi);
+            //把属性加入到Type。  
+            return AddPropertyToType(classType, lcpi);
+        }
+
+
+        /// <summary>  
+        /// 添加属性到类型的实例,注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="classType">指定类型的实例。</param>  
+        /// <param name="cpi">表示一个属性。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type AddProperty(this Type classType, CustPropertyInfo cpi)
+        {
+            List<CustPropertyInfo> lcpi = new List<CustPropertyInfo>
+            {
+                cpi
+            };
+            //合并先前的属性,以便一起在下一步进行处理。  
+            MergeProperty(classType, lcpi);
+            //把属性加入到Type。  
+            return AddPropertyToType(classType, lcpi);
+        }
+
+        /// <summary>
+        /// 给对象实例添加新属性并返回新对象实例
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="lcpi">自定义属性对象集合</param>
+        /// <returns></returns>
+        public static object AddProperty(this object obj, List<CustPropertyInfo> lcpi)
+        {
+            Type originType = obj.GetType();
+            var customs = lcpi.ToDictionary(i => i.PropertyName, i => i.PropertyValue);
+            var dest = AddProperty(originType, lcpi).CreateInstance();
+            foreach (var originProperty in originType.GetProperties())
+            {
+                dest.SetProperty(originProperty.Name, originProperty.GetValue(obj));
+            }
+            foreach (var cpi in customs)
+            {
+                dest.SetProperty(cpi.Key, cpi.Value);
+            }
+            return dest;
+        }
+
+        /// <summary>
+        /// 给对象实例添加新属性并返回新对象实例
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="cpi">自定义属性对象</param>
+        /// <returns></returns>
+        public static object AddProperty(this object obj, CustPropertyInfo cpi)
+        {
+            return AddProperty(obj, new List<CustPropertyInfo>() { cpi });
+        }
+
+        /// <summary>  
+        /// 从类型的实例中移除属性,注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="classType">指定类型的实例。</param>  
+        /// <param name="propertyName">要移除的属性。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type DeleteProperty(this Type classType, string propertyName)
+        {
+            List<string> ls = new List<string>
+            {
+                propertyName
+            };
+
+            //合并先前的属性,以便一起在下一步进行处理。  
+            List<CustPropertyInfo> lcpi = SeparateProperty(classType, ls);
+            //把属性加入到Type。  
+            return AddPropertyToType(classType, lcpi);
+        }
+
+
+        /// <summary>  
+        /// 从类型的实例中移除属性,注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="classType">指定类型的实例。</param>  
+        /// <param name="propertyNames">要移除的属性列表。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type DeleteProperty(this Type classType, List<string> propertyNames)
+        {
+            //合并先前的属性,以便一起在下一步进行处理。  
+            List<CustPropertyInfo> lcpi = SeparateProperty(classType, propertyNames);
+            //把属性加入到Type。  
+            return AddPropertyToType(classType, lcpi);
+        }
+
+        /// <summary>
+        /// 删除对象的属性并返回新对象实例
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="propertyNames">属性名集合</param>
+        /// <returns></returns>
+        public static object DeleteProperty(this object obj, List<string> propertyNames)
+        {
+            PropertyInfo[] oldProperties = obj.GetType().GetProperties();
+            Type t = obj.GetType();
+            foreach (string p in propertyNames)
+            {
+                t = t.DeleteProperty(p);
+            }
+            var newInstance = t.CreateInstance();
+            foreach (var p in newInstance.GetProperties())
+            {
+                newInstance.SetProperty(p.Name, oldProperties.FirstOrDefault(i => i.Name.Equals(p.Name)).GetValue(obj));
+            }
+            return newInstance;
+        }
+
+        /// <summary>
+        /// 删除对象的属性并返回新对象实例
+        /// </summary>
+        /// <param name="obj"></param>
+        /// <param name="property">属性名</param>
+        /// <returns></returns>
+        public static object DeleteProperty(this object obj, string property)
+        {
+            return DeleteProperty(obj, new List<string>() { property });
+        }
+        #endregion
+
+        #region 私有方法  
+
+        /// <summary>  
+        /// 把类型的实例t和lcpi参数里的属性进行合并。  
+        /// </summary>  
+        /// <param name="t">实例t</param>  
+        /// <param name="lcpi">里面包含属性列表的信息。</param>  
+        private static void MergeProperty(Type t, List<CustPropertyInfo> lcpi)
+        {
+            foreach (PropertyInfo pi in t.GetProperties())
+            {
+                CustPropertyInfo cpi = new CustPropertyInfo(pi.PropertyType, pi.Name);
+                lcpi.Add(cpi);
+            }
+        }
+
+
+        /// <summary>  
+        /// 从类型的实例t的属性移除属性列表lcpi,返回的新属性列表在lcpi中。  
+        /// </summary>  
+        /// <param name="t">类型的实例t。</param>  
+        /// <param name="ls">要移除的属性列表。</param>  
+        private static List<CustPropertyInfo> SeparateProperty(Type t, List<string> ls)
+        {
+            List<CustPropertyInfo> ret = new List<CustPropertyInfo>();
+            foreach (PropertyInfo pi in t.GetProperties())
+            {
+                foreach (string s in ls)
+                {
+                    if (pi.Name != s)
+                    {
+                        CustPropertyInfo cpi = new CustPropertyInfo(pi.PropertyType, pi.Name);
+                        ret.Add(cpi);
+                    }
+                }
+            }
+
+            return ret;
+        }
+
+
+        /// <summary>  
+        /// 把lcpi参数里的属性加入到myTypeBuilder中。注意:该操作会将其它成员清除掉,其功能有待完善。  
+        /// </summary>  
+        /// <param name="myTypeBuilder">类型构造器的实例。</param>  
+        /// <param name="lcpi">里面包含属性列表的信息。</param>  
+        private static void AddPropertyToTypeBuilder(TypeBuilder myTypeBuilder, List<CustPropertyInfo> lcpi)
+        {
+            // 属性Set和Get方法要一个专门的属性。这里设置为Public。  
+            var getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
+
+            // 添加属性到myTypeBuilder。  
+            foreach (CustPropertyInfo cpi in lcpi)
+            {
+                //定义字段。  
+                FieldBuilder customerNameBldr = myTypeBuilder.DefineField(cpi.FieldName, cpi.Type, FieldAttributes.Private);
+                //customerNameBldr.SetConstant("11111111");
+                //定义属性。  
+                //最后一个参数为null,因为属性没有参数。  
+                var custNamePropBldr = myTypeBuilder.DefineProperty(cpi.PropertyName, PropertyAttributes.HasDefault, cpi.Type, null);
+
+                //custNamePropBldr.SetConstant("111111111");
+                //定义Get方法。  
+                var custNameGetPropMthdBldr = myTypeBuilder.DefineMethod(cpi.GetPropertyMethodName, getSetAttr, cpi.Type, Type.EmptyTypes);
+
+                var custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();
+
+                try
+                {
+                    custNameGetIL.Emit(OpCodes.Ldarg_0);
+                    //custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);  
+                    custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);
+                    custNameGetIL.Emit(OpCodes.Ret);
+                }
+                catch (Exception)
+                {
+                    // ignored
+                }
+
+                //定义Set方法。  
+                var custNameSetPropMthdBldr = myTypeBuilder.DefineMethod(cpi.SetPropertyMethodName, getSetAttr, null, new[]
+                {
+                    cpi.Type
+                });
+
+                var custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();
+
+                custNameSetIL.Emit(OpCodes.Ldarg_0);
+                custNameSetIL.Emit(OpCodes.Ldarg_1);
+                custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);
+                custNameSetIL.Emit(OpCodes.Ret);
+                //custNamePropBldr.SetConstant("ceshi");  
+                //把创建的两个方法(Get,Set)加入到PropertyBuilder中。  
+                custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
+                custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);
+            }
+        }
+
+
+        /// <summary>  
+        /// 把属性加入到类型的实例。  
+        /// </summary>  
+        /// <param name="classType">类型的实例。</param>  
+        /// <param name="lcpi">要加入的属性列表。</param>  
+        /// <returns>返回处理过的类型的实例。</returns>  
+        public static Type AddPropertyToType(this Type classType, List<CustPropertyInfo> lcpi)
+        {
+            AssemblyName myAsmName = new AssemblyName
+            {
+                Name = "MyDynamicAssembly"
+            };
+
+            //创建一个程序集,设置为AssemblyBuilderAccess.RunAndCollect。  
+            AssemblyBuilder myAsmBuilder = AssemblyBuilder.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndCollect);
+
+            //创建一个单模程序块。  
+            ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name);
+            //创建TypeBuilder。  
+            // ReSharper disable once AssignNullToNotNullAttribute
+            TypeBuilder myTypeBuilder = myModBuilder.DefineType(classType.FullName, TypeAttributes.Public);
+
+            //把lcpi中定义的属性加入到TypeBuilder。将清空其它的成员。其功能有待扩展,使其不影响其它成员。  
+            AddPropertyToTypeBuilder(myTypeBuilder, lcpi);
+
+            //创建类型。  
+            Type retval = myTypeBuilder.CreateType();
+
+            //保存程序集,以便可以被Ildasm.exe解析,或被测试程序引用。  
+            //myAsmBuilder.Save(myAsmName.Name + ".dll");  
+            return retval;
+        }
+
+        #endregion
+
+        #region 辅助类  
+
+        /// <summary>  
+        /// 自定义的属性信息类型。  
+        /// </summary>  
+        public class CustPropertyInfo
+        {
+            /// <summary>  
+            /// 空构造。  
+            /// </summary>  
+            public CustPropertyInfo()
+            {
+            }
+
+            /// <summary>  
+            /// 根据属性类型名称,属性名称构造实例。  
+            /// </summary>  
+            /// <param name="type">属性类型名称。</param>  
+            /// <param name="propertyName">属性名称。</param>  
+            public CustPropertyInfo(Type type, string propertyName)
+            {
+                Type = type;
+                PropertyName = propertyName;
+            }
+
+            public CustPropertyInfo(Type type, string propertyName, object propertyValue) : this(type, propertyName)
+            {
+                PropertyValue = propertyValue;
+            }
+
+            /// <summary>  
+            /// 获取或设置属性类型名称。  
+            /// </summary>  
+            public Type Type { get; set; }
+
+            /// <summary>  
+            /// 获取或设置属性名称。  
+            /// </summary>  
+            public string PropertyName { get; set; }
+
+            /// <summary>
+            /// 属性值
+            /// </summary>
+            public object PropertyValue { get; set; }
+
+            /// <summary>  
+            /// 获取属性字段名称。  
+            /// </summary>  
+            public string FieldName
+            {
+                get
+                {
+                    if (PropertyName.Length < 1)
+                    {
+                        return "";
+                    }
+
+                    return PropertyName.Substring(0, 1).ToLower() + PropertyName.Substring(1);
+                }
+            }
+
+            /// <summary>  
+            /// 获取属性在IL中的Set方法名。  
+            /// </summary>  
+            public string SetPropertyMethodName => "set_" + PropertyName;
+
+
+            /// <summary>  
+            ///  获取属性在IL中的Get方法名。  
+            /// </summary>  
+            public string GetPropertyMethodName => "get_" + PropertyName;
+        }
+
+        #endregion
+    }
+}

+ 8 - 3
NetCoreTest/Controllers/HomeController.cs

@@ -1,13 +1,18 @@
-using Masuit.Tools.Files;
+using Masuit.Tools.Core.NoSQL;
+using Masuit.Tools.Files;
+using Masuit.Tools.NoSQL;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.Mvc;
 
 
 namespace NetCoreTest.Controllers
 namespace NetCoreTest.Controllers
 {
 {
     public class HomeController : Controller
     public class HomeController : Controller
     {
     {
-        public void Zip()
+        public RedisHelper RedisHelper { get; set; }
+        public HomeController(RedisHelperFactory redisHelperFactory)
         {
         {
-            ClassZip.Zip(@"H:\Dism++", @"H:\1.zip", 9);
+            RedisHelper=redisHelperFactory.Create("aa",0);// 创建命名为aa的RedisHelper,指定数据库0
+            RedisHelper=redisHelperFactory.CreateDefault(0); // 创建默认的RedisHelper,指定数据库0
+            RedisHelper=redisHelperFactory.CreateLocal(0); // 创建连接本机的RedisHelper,指定数据库0
         }
         }
     }
     }
 }
 }

+ 3 - 3
NetCoreTest/Startup.cs

@@ -19,9 +19,9 @@ namespace NetCoreTest
         // This method gets called by the runtime. Use this method to add services to the container.
         // This method gets called by the runtime. Use this method to add services to the container.
         public void ConfigureServices(IServiceCollection services)
         public void ConfigureServices(IServiceCollection services)
         {
         {
-            services.AddDefaultRedisHelper("192.168.16.145:6379,password=xilife2018,connectTimeout=1000,connectRetry=1,syncTimeout=1000");
-            services.AddLocalRedisHelper();
-            services.AddRedisHelper("aa", "192.168.16.145:6379,password=xilife2018,connectTimeout=1000,connectRetry=1,syncTimeout=1000");
+            services.AddDefaultRedisHelper("192.168.16.145:6379,password=xilife2018,connectTimeout=1000,connectRetry=1,syncTimeout=1000");//注入一个默认实例
+            services.AddLocalRedisHelper();// 注入本地实例
+            services.AddRedisHelper("aa", "192.168.16.145:6379,password=xilife2018,connectTimeout=1000,connectRetry=1,syncTimeout=1000");// 通用注入
             services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
             services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
         }
         }