林豪 左 3 年之前
父節點
當前提交
ed7e3c75d4

+ 4 - 0
.editorconfig

@@ -0,0 +1,4 @@
+[*.cs]
+
+# CS8600: 将 null 字面量或可能为 null 的值转换为非 null 类型。
+dotnet_diagnostic.CS8600.severity = none

+ 47 - 0
WCS.Core/BaseExtensions/AssemblyExtension.cs

@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace WCS.Core.BaseExtensions
+{
+    /// <summary>
+    /// 针对程序集操作的扩展
+    /// </summary>
+    public static class AssemblyExtension
+    {
+        /// <summary>
+        /// 删除重复的程序集
+        /// </summary>
+        /// <param name="assemblies"></param>
+        public static IEnumerable<Assembly> RemoveDuplicateAssemblies(this IEnumerable<Assembly> assemblies)
+        {
+            return assemblies.DistinctBy(p => p.FullName);
+        }
+
+        /// <summary>
+        /// 删除指定名称的程序集
+        /// </summary>
+        /// <param name="assemblyNames"></param>
+        /// <returns></returns>
+        public static IEnumerable<AssemblyName> RemoveTheAssemblyNamespecified(this IEnumerable<AssemblyName> assemblyNames)
+        {
+            return assemblyNames.Where(p => p.Name != null && !p.Name.StartsWith("System."))
+                .Where(p => !p.Name.StartsWith("mscorlib."))
+                .Where(p => !p.Name.StartsWith("netstandard."))
+                .Where(p => !p.Name.StartsWith("Senparc."))
+                .Where(p => !p.Name.StartsWith("Newtonsoft."))
+                .Where(p => !p.Name.StartsWith("UnityEngine."))
+                .Where(p => !p.Name.StartsWith("ZKWeb."))
+                .Where(p => !p.Name.StartsWith("NPOI."))
+                .Where(p => !p.Name.StartsWith("ICSharpCode."))
+                .Where(p => !p.Name.StartsWith("NLog"))
+                .Where(p => !p.Name.StartsWith("e_sqlite"))
+                .Where(p => !p.Name.StartsWith("MsgPack."))
+                .Where(p => !p.Name.StartsWith("netstandard"))
+                .Where(p => !p.Name.StartsWith("Jiguang"))
+                .Where(p => !p.Name.StartsWith("StackExchange"))
+                .Where(p => !p.Name.StartsWith("Microsoft."))
+                .Where(p => !p.Name.StartsWith("TIBCO."));
+        }
+    }
+}

+ 30 - 0
WCS.Core/BaseExtensions/LinqExtension.cs

@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+
+namespace WCS.Core.BaseExtensions
+{
+    /// <summary>
+    /// Linq 扩展
+    /// </summary>
+    public static class LinqExtension
+    {
+        /// <summary>
+        /// 根据指定的属性返回集合中的非重复元素
+        /// </summary>
+        /// <remarks>不明白本方法是如何实现去重的</remarks>
+        /// <typeparam name="TSource">数据源的类型</typeparam>
+        /// <typeparam name="TKey">数据源需要进行筛选的属性</typeparam>
+        /// <param name="source">数据源</param>
+        /// <param name="keySelector">指定属性的函数表达式</param>
+        /// <returns></returns>
+        public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            var seenKeys = new HashSet<TKey>();
+            foreach (var source1 in source)
+            {
+                if (seenKeys.Add(keySelector(source1)))
+                    yield return source1;
+            }
+        }
+    }
+}

+ 173 - 0
WCS.Core/Helpers/ReflectionHelper.cs

@@ -0,0 +1,173 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using WCS.Core.BaseExtensions;
+
+namespace WCS.Core.Helpers
+{
+    /// <summary>
+    /// 反射辅助类
+    /// </summary>
+    public class ReflectionHelper
+    {
+        /// <summary>
+        /// 创建指定类型的实例
+        /// </summary>
+        /// <typeparam name="TModel"></typeparam>
+        /// <param name="type"></param>
+        /// <returns></returns>
+        public static TModel CreateInstance<TModel>(Type type) => (TModel)ReflectionHelper.CreateInstance(type);
+
+        /// <summary>
+        /// 创建指定类型的实例
+        /// </summary>
+        /// <param name="type"></param>
+        /// <returns></returns>
+        public static object CreateInstance(Type type) => Activator.CreateInstance(type);
+
+        /// <summary>
+        /// 从当前程序中 获取所有实现指定接口的类型
+        /// </summary>
+        /// <typeparam name="TInterface"></typeparam>
+        /// <returns></returns>
+        public static List<Type> GetTypesByImplementInterface<TInterface>() where TInterface : class => GetAssemblies().SelectMany(GetTypesByImplementInterface<TInterface>).ToList();
+
+        /// <summary>
+        /// 从指定的程序集里 获取所有实现指定接口的类型
+        /// </summary>
+        /// <typeparam name="TInterface"></typeparam>
+        /// <param name="assembly"></param>
+        /// <returns></returns>
+        public static List<Type> GetTypesByImplementInterface<TInterface>(Assembly assembly) where TInterface : class
+        {
+            try
+            {
+                return assembly.GetTypes() //获取该程序集中所有的类
+                               .Where(type => !string.IsNullOrWhiteSpace(type.Namespace))//命名空间不为空
+                               .Where(type => type.GetTypeInfo().IsClass) //必须要有类
+                               .Where(type => type.GetTypeInfo().BaseType != null)//基本类型不为空
+                               .Where(type => !type.GetTypeInfo().IsAbstract) //没有作废弃用
+                                                                              // IsAssignableFrom
+                                                                              // 方法的作用
+                                                                              // a对象所对应类信息是b对象所对应的类信息的父类或者是父接口,简单理解即a是b的父类或接口 a对象所对应类信息与b对象所对应的类信息相同,简单理解即a和b为同一个类或同一个接口
+                               .Where(type => typeof(TInterface).IsAssignableFrom(type))// 当前类是否继承或指定接口
+                               .ToList();
+            }
+            catch
+            {
+                return new List<Type>();
+            }
+        }
+
+        /// <summary>
+        /// 从指定的程序集里 获取所有实现指定接口的类型
+        /// </summary>
+        /// <typeparam name="TInterface"></typeparam>
+        /// <param name="assemblies"></param>
+        /// <returns></returns>
+        public static List<Type> GetTypesByImplementInterface<TInterface>(List<Assembly> assemblies) where TInterface : class
+        {
+            try
+            {
+                List<Type> types = new List<Type>();
+                assemblies.ForEach(p =>
+                {
+                    types.AddRange(p.GetTypes() //获取该程序集中所有的类
+                               .Where(type => !string.IsNullOrWhiteSpace(type.Namespace))//命名空间不为空
+                               .Where(type => type.GetTypeInfo().IsClass) //必须要有类
+                               .Where(type => type.GetTypeInfo().BaseType != null)//基本类型不为空
+                               .Where(type => !type.GetTypeInfo().IsAbstract) //没有作废弃用
+                                                                              // IsAssignableFrom
+                                                                              // 方法的作用
+                                                                              // a对象所对应类信息是b对象所对应的类信息的父类或者是父接口,简单理解即a是b的父类或接口 a对象所对应类信息与b对象所对应的类信息相同,简单理解即a和b为同一个类或同一个接口
+                               .Where(type => typeof(TInterface).IsAssignableFrom(type))// 当前类是否继承或指定接口
+                               .ToList());
+                });
+
+                return types;
+            }
+            catch
+            {
+                return new List<Type>();
+            }
+        }
+
+        /// <summary>
+        /// 获取项目中所有程序集 (注意,排除了一些指定的程序集)
+        /// </summary>
+        /// <remarks>AppContext.BaseDirectory 方法的作用是获取程序所在目录</remarks>
+        /// <returns></returns>
+        public static List<Assembly> GetAssemblies()
+        {
+            var assemblies = new List<Assembly>();
+            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
+            {
+                assembly.GetReferencedAssemblies().RemoveTheAssemblyNamespecified().ToList()
+                    .ForEach(p =>
+                    {
+                        try
+                        {
+                            assemblies.Add(Assembly.Load(p));
+                        }
+                        catch (Exception ex)
+                        {
+                            Log("  警告! 加载程序集失败:" + p.FullName);
+                            Log("     错误: " + ex.Message);
+                        }
+                    });
+            }
+            assemblies.AddRange(GetAssemblies(AppContext.BaseDirectory));
+            return assemblies.RemoveDuplicateAssemblies().ToList();
+        }
+
+        /// <summary>
+        /// 从指定的目录开始,提取所有可用的程序集,向上查找引用的
+        /// </summary>
+        /// <param name="path"></param>
+        /// <returns></returns>
+        public static List<Assembly> GetAssemblies(string path)
+        {
+            var source = new List<Assembly>(); //需要返回的数据集合
+            foreach (var file in Directory.GetFiles(path, "*.dll"))//读取指定目录中所有的DLL文件路径,并遍历
+            {
+                //try
+                //{
+                var a = Assembly.GetEntryAssembly();
+                var assembly = Assembly.LoadFrom(file); //将获取到的程序集加载出来
+                source.Add(assembly); //将该程序集加入到需要返回的数据中
+                                      //找到所有引用过这个程序集的程序集的名称,并进行遍历
+                assembly.GetReferencedAssemblies().RemoveTheAssemblyNamespecified().ToList()
+                        .ForEach(p =>
+                        {
+                            try
+                            {
+                                source.Add(Assembly.Load(p));
+                            }
+                            catch (Exception ex)
+                            {
+                                Log("  警告! 加载程序集失败:" + p.FullName);
+                                Log("     错误: " + ex.Message);
+                            }
+                        });
+                //}
+                //catch (Exception ex)
+                //{
+                //    Log("  警告! 提取程序集失败:" + file);
+                //    Log("     错误: " + ex.Message);
+                //}
+            }
+            return source.DistinctBy(p => p.FullName).ToList();
+        }
+
+        /// <summary>
+        /// 写日志
+        /// </summary>
+        /// <param name="_">日志内容</param>
+        private static void Log(string _)
+        {
+        }
+    }
+}

+ 1 - 1
WCS.Core/Properties/PublishProfiles/FolderProfile.pubxml

@@ -8,6 +8,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
     <Platform>Any CPU</Platform>
     <PublishDir>D:\XM\Release\DLL</PublishDir>
     <PublishProtocol>FileSystem</PublishProtocol>
-    <VersionPrefix>1.0.7</VersionPrefix>
+    <VersionPrefix>1.0.8</VersionPrefix>
   </PropertyGroup>
 </Project>

+ 1 - 1
WCS.Service/DeviceExtentions.cs

@@ -1,4 +1,4 @@
-using DbHelper;
+using WCS.Core.DbHelper;
 using WCS.Entity;
 using WCS.Entity.Protocol;
 using WCS.Entity.Protocol.Station;

+ 2 - 2
WCS.Service/PLCAccessors/SiemensS7PLC.cs

@@ -1,8 +1,8 @@
 using HslCommunication.Profinet.Siemens;
-using WCS.BaseExtensions;
 using WCS.Core;
+using WCS.Core.BaseExtensions;
 using WCS.Core.DataTrans;
-using WCS.Virtual_PLC;
+using WCS.Core.Virtual_PLC;
 
 namespace WCS.Service.PLCAccessors
 {

+ 3 - 3
WCS.Service/ProtocolProxy.cs

@@ -1,5 +1,4 @@
-using DbHelper;
-using FreeRedis;
+using FreeRedis;
 using MessagePack;
 using MessagePack.Resolvers;
 using SqlSugar;
@@ -7,9 +6,10 @@ using System.Collections.Concurrent;
 using System.Diagnostics;
 using System.Linq.Dynamic.Core;
 using System.Reflection;
-using WCS.BaseExtensions;
 using WCS.Core;
+using WCS.Core.BaseExtensions;
 using WCS.Core.DataTrans;
+using WCS.Core.DbHelper;
 using WCS.Entity;
 using WCS.Entity.Protocol;
 

+ 2 - 2
WCS.Service/Uploader.cs

@@ -1,5 +1,5 @@
-using DbHelper;
-using Log;
+using WCS.Core.DbHelper;
+using WCS.Core.Log;
 using WCS.Entity;
 using WCS.WebApi.WMS;
 

+ 3 - 2
WCS.Service/WCS.Service.csproj

@@ -25,7 +25,8 @@
     <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
     <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.8" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
-    <PackageReference Include="WCS.Core" Version="1.0.7" />
-    <PackageReference Include="WCS.WorkEngineering" Version="1.0.2" />
+    <PackageReference Include="WCS.Core" Version="1.0.8" />
+    <PackageReference Include="WCS.Entity.Protocol" Version="1.0.2" />
+    <PackageReference Include="WCS.WebApi" Version="1.0.2" />
   </ItemGroup>
 </Project>

+ 5 - 5
WCS.Service/Worker.cs

@@ -1,16 +1,16 @@
-using DbHelper;
-using Log;
 using Newtonsoft.Json;
 using SqlSugar;
-using System.Reflection;
 using System.Text;
 using WCS.Core;
 using WCS.Core.DataTrans;
+using WCS.Core.DbHelper;
+using WCS.Core.Helpers;
+using WCS.Core.Log;
+using WCS.Core.Virtual_PLC;
 using WCS.Entity;
 using WCS.Entity.Protocol;
 using WCS.Entity.Protocol.BCR;
 using WCS.Entity.Protocol.Station;
-using WCS.Virtual_PLC;
 using WCS.WebApi.WMS;
 
 namespace WCS.Service
@@ -177,7 +177,7 @@ namespace WCS.Service
 
                 #region ÆôÓÃËùÓеÄÂß¼­´¦ÀíÆ÷
 
-                var managerTypes = Assembly.GetExecutingAssembly().GetTypes().Where(v => v.IsSubclassOf(typeof(LogicHandler)) && !v.IsGenericType && !v.IsAbstract).ToArray();
+                var managerTypes = ReflectionHelper.GetTypesByImplementInterface<LogicHandler>().ToArray();
                 foreach (var type in managerTypes)
                 {
                     var m = Activator.CreateInstance(type);