未能加载文件或程序集,或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配-坤哥网

mikel阅读(1879)

来源: 未能加载文件或程序集,或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配-坤哥网

我们在开发中经常会出现程序引用不匹配的问题。

下面是遇到的一个具体实例:

InnerException = {“未能加载文件或程序集“log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=1b44e1d426115821”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)”:”log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=1b44e1d426115821″}

项目引用的是 2.0.8.0 版本。

这个实例刚开始压根没找到原因,因为在配置文件中的程序集并没有配置:

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
      </dependentAssembly>    
    </assemblyBinding>

原来项目中引用的另外的 dll 引用了 老版本的 log4net。

把项目中的引用的 log4net 改成老版本,但是有其他的引用又引用了新版本的 log4net,真是头大:

log4net:ERROR XmlHierarchyConfigurator: Could not create Appender [KafkaAppender] of type [Cn.Vcredit.ELK.LogAppender.Log4NetForKFKExt.Appender.KafkaAppender, Cn.Vcredit.ELK.LogAppender]. Reported error follows.
System.IO.FileLoadException: 未能加载文件或程序集“log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
文件名:“log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a”
   在 System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
   在 System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
   在 System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase)
   在 log4net.Util.SystemInfo.GetTypeFromString(Assembly relativeAssembly, String typeName, Boolean throwOnError, Boolean ignoreCase)
   在 log4net.Util.SystemInfo.GetTypeFromString(String typeName, Boolean throwOnError, Boolean ignoreCase)
   在 log4net.Repository.Hierarchy.XmlHierarchyConfigurator.ParseAppender(XmlElement appenderElement)

=== 预绑定状态信息 ===
日志: DisplayName = log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a
 (Fully-specified)
日志: Appbase = file:///D:/svn/Loan/trunk/VBS_Console/Cn.Vcredit.VBS.BlackStatistics/Cn.Vcredit.VBS.BlackStatistics/bin/Debug/
日志: 初始 PrivatePath = NULL
调用程序集: Cn.Vcredit.ELK.LogAppender, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null。
===
日志: 此绑定从 default 加载上下文开始。
日志: 正在使用应用程序配置文件: D:\svn\Loan\trunk\VBS_Console\Cn.Vcredit.VBS.BlackStatistics\Cn.Vcredit.VBS.BlackStatistics\bin\Debug\Cn.Vcredit.VBS.BlackStatistics.vshost.exe.Config
日志: 使用主机配置文件:
日志: 使用 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config 的计算机配置文件。
日志: 策略后引用: log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a
日志: 尝试下载新的 URL file:///D:/svn/Loan/trunk/VBS_Console/Cn.Vcredit.VBS.BlackStatistics/Cn.Vcredit.VBS.BlackStatistics/bin/Debug/log4net.DLL。
警告: 比较程序集名称时发生不匹配: 主版本
错误: 未能完成程序集的安装(hr = 0x80131040)。探测终止。

log4net:ERROR XmlHierarchyConfigurator: Appender named [KafkaAppender] not found.

如何解决这个问题呢?

方案一:

这种情况可以让两个版本共存,如果是 publicKeyToken 需要使用两个 dependentAssembly 节点。

如何获取 publicKeyToken(公钥标记)  值,只需要使用 SN 命令即可,找到 SN.exe 程序,可以使用搜索工具找到,如下:

2e8bcfc2-4308-4d73-ac36-ac5d98ff55c8.png

选择一个比如:C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\x6464e2fe5f-6786-4dcc-8ede-e9c781c9531a.png

打开命令窗口,定位到这个目录,使用命令 SN -T “dll的路径”:20e5eb6c-48d9-4fda-a690-853ac4cf589e.png

在项目的配置文件中找到 assemblyBinding 节点下面添加 dependentAssembly:

<dependentAssembly>  
      <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" />  
      <codeBase version="1.2.10.0" href="bin\Debug\log4netdll\1_2_10\log4net.dll" />  
    </dependentAssembly>  
    <dependentAssembly>  
      <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" />  
      <codeBase version="2.0.8.0" href="bin\Debug\log4netdll\2_0_8\log4net.dll" />  
    </dependentAssembly>

方案二:

将引用的dll中对目标dll的引用改成统一版本。

ASP.NET SignalR 系列(一)之SignalR介绍 - 黄明辉 - 博客园

mikel阅读(1068)

来源: ASP.NET SignalR 系列(一)之SignalR介绍 – 黄明辉 – 博客园

一、SignalR介绍

ASP.NET SignalR 是一个面向 ASP.NET 开发人员的库,可简化将实时 web 功能添加到应用程序的过程。 实时 web 功能是让服务器代码将内容推送到连接的客户端立即可用,而不是让服务器等待客户端请求新数据的能力。

废话不多说

传输模式

 

二、SignalR 和 WebSocket的区别

简单的说呢,websocket对客户端和服务端都有要求,而SignalR对兼容性就比较好,它集成了WebScoket和http两种方式,当条件满足时,自动使用WebScoket,否则使用http。可以简单的理解为,WebScoket是SignalR的子集。

 

三、SignalR的两种模式
永久连接

长连接(长轮询)

1、如果浏览器是 Internet Explorer 8 或更早版本,则使用长轮询。

2、如果配置 JSONP (即jsonp参数设置为true启动连接时),使用长轮询。

3、如果操作正在进行的跨域连接,(即,如果 SignalR 终结点不在托管的页面所在的域中),然后 WebSocket 将在满足以下条件:

                      1、客户端支持 CORS (跨域资源共享)。

                      2、客户端支持 WebSocket

                      3、服务器支持 WebSocket

                     4、如果不满足任何这些条件,则将使用长轮询。

4、如果未配置 JSONP 并且连接不跨域,如果客户端和服务器支持它,则将使用 WebSocket。

5、如果客户端或服务器不支持 WebSocket,如果可用,则使用服务器发送事件。

6、如果服务器发送事件不可用,请尝试使用永久帧。

7、如果永久连接失败,则使用长轮询。

文章介绍参考:https://docs.microsoft.com/zh-cn/aspnet/signalr/overview/getting-started/introduction-to-signalr#signalr-and-websocket

不在多介绍了,下章开始进入撸代码。

.net/c# 引用dll版本冲突解决办法_.Net/C#_架构师_程序员

mikel阅读(2239)

来源: .net/c# 引用dll版本冲突解决办法_.Net/C#_架构师_程序员

未能加载文件或程序集“Common.Logging, Version=2.1.1.0, Culture=neutral, PublicKeyToken=af08829b84f0328e”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)

说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。

异常详细信息: System.IO.FileLoadException: 未能加载文件或程序集“Common.Logging, Version=2.1.1.0, Culture=neutral, PublicKeyToken=af08829b84f0328e”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)

源错误:

执行当前 Web 请求期间生成了未经处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。

程序集加载跟踪: 下列信息有助于确定程序集“Common.Logging, Version=2.1.1.0, Culture=neutral, PublicKeyToken=af08829b84f0328e”未能加载的原因。

有时候,我们会看到上面的错误。

错误原因

A项目引用了xxx.dll,B项目也引用了xxx.dll,A项目引用了B项目,如下图:

A项目和B项目都引用了xxx.dll,但是,A项目引用的是高版本的dll,B项目引用的是低版本的dll,当A项目运行的时候,就会报错,找不到低版本的dll

解决办法

利用<bindingRedirect>元素,将一个程序集版本重定向到另一个版本。

oldVersion       

  • 必需的特性
  • 指定最初请求的程序集的版本。 程序集版本号的格式是major.minor.build.revision。 该版本号的每个部分的有效值介于 0 和 65535 之间。
  • 你还可以按下列格式指定版本范围:
  • n.n.n.n-n.n.n.n

newVersion

  • 必需的特性。
  • 指定要使用而不是最初请求的版本格式的程序集的版本: n.n.n.n
  • 此值可以指定 oldVersion 之前的版本。

文档链接:https://docs.microsoft.com/zh-cn … ingredirect-element

官方例子:

  1. <configuration>
  2.    <runtime>
  3.       <assemblyBinding xmlns=”urn:schemas-microsoft-com:asm.v1″>
  4.          <dependentAssembly>
  5.             <assemblyIdentity name=”myAssembly”
  6.                               publicKeyToken=”32ab4ba45e0a69a1″
  7.                               culture=”neutral” />
  8.             <bindingRedirect oldVersion=”1.0.0.0″
  9.                              newVersion=”2.0.0.0″/>
  10.          </dependentAssembly>
  11.       </assemblyBinding>
  12.    </runtime>
  13. </configuration>

复制代码

所以,我的解决办法是在web.config设置如下:

  1. <dependentAssembly>
  2.         <assemblyIdentity name=”Common.Logging” publicKeyToken=”af08829b84f0328e” culture=”neutral” />
  3.         <bindingRedirect oldVersion=”0.0.0.0-3.3.1.0″ newVersion=”3.3.1.0″ />
  4.       </dependentAssembly>

Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室) - 果冻布丁喜之郎 - 博客园

mikel阅读(707)

来源: Asp.NET MVC 使用 SignalR 实现推送功能一(Hubs 在线聊天室) – 果冻布丁喜之郎 – 博客园

简介

      ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信。什么是实时通信的Web呢?就是让客户端(Web页面)和服务器端可以互相通知消息及调用方法,当然这是实时操作的。
WebSockets是HTML5提供的新的API,可以在Web网页与服务器端间建立Socket连接,当WebSockets可用时(即浏览器支持Html5)SignalR使用WebSockets,当不支持时SignalR将使用其它技术来保证达到相同效果。
SignalR当然也提供了非常简单易用的高阶API,使服务器端可以单个或批量调用客户端上的JavaScript函数,并且非常 方便地进行连接管理,例如客户端连接到服务器端,或断开连接,客户端分组,以及客户端授权,使用SignalR都非常 容易实现。
SignalR 将与客户端进行实时通信带给了ASP .NET 。当然这样既好用,而且也有足够的扩展性。以前用户需要刷新页面或使用Ajax轮询才能实现的实时显示数据,现在只要使用SignalR,就可以简单实现了。
最重要的是您无需重新建立项目,使用现有ASP .NET项目即可无缝使用SignalR。
  以上是来自百度百科的解释,个人觉得通俗来讲就是WebSockets是一种握手协议,当用户于服务器建立连接(握手成功)时,双方就建立了一个连接通道,互相传递时时数据。在这之前,我们一般来说实现这个功能的方式就是Ajax轮询,通过Ajax循环获取数据,这当然是非常消耗资源的,并且给服务器带来一定的压力。而WebSockets虽然可达到全双工通信,但依然需要发出请求,不过这种请求的Header是很小的-大概只有 2 Bytes。这里我们重点要知道的一点就是,WebSockets这个通道是双工通道,简单理解就是客户端(JavaScriptJQuery)的方法不但可以调取服务器的功能程序方法,并且服务器的功能程序也可以调取全部(广播)或某个(单播)或某一类(组播)客户端(javascript、JQuery)的方法。而SignalR则是微软给我们集成的一个WebSockets API,原理跟WebSockets是一致的,只是当WebSockets可用时(即浏览器支持Html5)SignalR使用WebSockets,当不支持时SignalR将使用其它技术来保证达到相同效果。

使用

很多新的技术没有必要非得理解,只需要知道你的应用环境可以用这项技术很简便的去实现,用的多了,用的久了,自然而然就会慢慢的理解这项技术的原理了。

今天我们一步一步来介绍一下如何使用SignalR,这一篇文章介绍的是使用Hubs SignalR集线器去实现,下一篇我们将介绍使用SignalR永久连接类去实现,我们做个简单的聊天室。

先给大家贴一下Demo的效果图:

一、准备:

SignalR 运行在 .NET 4.5 平台上,所以需要安装 .NET 4.5。为了方便演示,本示例使用 ASP.NET MVC 在 Win 7 系统来实现。这需要安装 ASP.NET MVC 3 或 ASP.NET MVC 4

二:Hubs代码示例:

1、首先我们创建一个MVC项目工程名字叫做SignalR_Chat

2、然后打开 工具 – NuGet程序包管理器 – 程序包管理器控制台

3、安装SignalR

输出NuGet命令:Install-Package Microsoft.AspNet.SignalR

安装成功后我们发现我们的bin里已经添加了我们需要的组件,并且在Scripts文件夹下添加了SignalR的JQuery引用

4、我们新建一个文件夹叫Hubs,然后添加SignalR集线器类ChatHub.cs

在上面的代码中:

(1)HubName 这个特性是为了让客户端知道如何建立与服务器端对应服务的代理对象,如果没有设定该属性,则以服务器端的服务类名字作为 HubName 的缺省值;

(2)Chat 继承自 Hub,从下面 Hub 的接口图可以看出:Hub 支持向发起请求者(Caller),所有客户端(Clients),特定组(Group) 推送消息。

5、添加OWIN Startup Class

修改 Configuration方法

复制代码
using Microsoft.Owin;
using Owin;
using SignalR_Chat.Connections;

[assembly: OwinStartupAttribute(typeof(SignalR_Chat.Startup))]
namespace SignalR_Chat
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
       //这个是下一篇永久连接类的 我们先不用
            //app.MapSignalR<MyConnection>("/echo");
        }
    }
}
复制代码

 

6、我们实现一个聊天室,代码我是分步贴出来的,后面我会附上完整的代码和Demo。

首先,我们新建一个类 标记用户和在线状态

复制代码
    public class OnlineUserInfo
        {
            //用户ID
            public string UserId { get; set; }
            //用户连接ID
            public string ConnectionId { get; set; }
            //用户昵称
            public string UserNickName { get; set; }
            //用户头像
            public string UserFaceImg { get; set; }
            //用户状态
            public string UserStates { get; set; }
        }
复制代码

然后,我们在ChatHub中实例化一下这个类

复制代码
       /// <summary>
        /// 这个是通过Hub集线器 大家可以参考 Connections下的 MyConnection 永久连接
        /// </summary>
        [HubName("chat")]
        public class ChatHub : Hub
        {
            static List<OnlineUserInfo> UserList = new List<OnlineUserInfo>();
        }
复制代码

我们写一个用户连接时注册一个群组,用户后面的组播

复制代码
            /// <summary>
            /// 注册群组 注册用户信息
            /// </summary>
            /// <param name="groupid">群组ID</param>
            /// <param name="usernickname">用户昵称</param>
            /// <param name="userfaceimg">用户头像</param>
            /// <param name="userid">用户在网站中的唯一标识ID</param>
            public void Group(string groupid, string usernickname, string userfaceimg, string userid)
            {
                //添加用户到群组 Groups.Add(用户连接ID,群组)
                Groups.Add(Context.ConnectionId, groupid);

                //如果说是一个简单的聊天室 下面这段代码是没有什么作用的 因为Context.ConnectionId是唯一的用户于服务器之间的连接
                //这里我传递进来了 用户的昵称和头像 还有网站中用户的ID 所以我要把用户的信息添加到我们上面建立的那个列表类中

                //如果用户不存在在线列表中
                if (UserList.Where(p => p.UserId == userid).FirstOrDefault() == null)
                {
                    //我们在列表中 添加这个用户 并且标记用户在线 UserStates = "True"
                    UserList.Add(new OnlineUserInfo() { UserId = userid, ConnectionId = Context.ConnectionId, UserNickName = usernickname, UserFaceImg = userfaceimg, UserStates = "True" });
                }
                    //如果用户已经存在于在线列表中
                else
                {
                    //我们更新用户列表中用户的信息 (这里更新的信息主要是用户的连接ID  ConnectionId = Context.ConnectionId)
                    var UserInfo = UserList.Where(p => p.UserId == userid).FirstOrDefault();
                    UserList.Remove(UserInfo);
                    UserList.Add(new OnlineUserInfo() { UserId = userid, ConnectionId = Context.ConnectionId, UserNickName = usernickname, UserFaceImg = userfaceimg, UserStates = "True" });
                }
                //这个方法是调用客户端LoginUser方法 并且传递当前用户列表 客户端会刷新当前用户列表 调用的是全部的已连接的用户 Clients.All
                Clients.All.LoginUser(Common.JsonConverter.Serialize(UserList));
                //这个方法是调用客户端的 addNewMessageToPage方法 目的是实现 当一个用户上线是 提醒所有的用户 某个用户上线了 提醒的是所有的已连接用户 所以也是Clients.All
                Clients.All.addNewMessageToPage("<dl  class=\"messageTip clearfix\"><dt></dt><dd>系统消息:" + DateTime.Now.ToString("HH:mm:ss") + "&nbsp;" + usernickname + "&nbsp;上线了<dd></dl>");
            }
复制代码

为了方便大家理解,我这里就先把客户端的LoginUser和addNewMessageToPage方法贴出来,让大家好理解服务器是怎样调用客户端的js方法的

复制代码
    //接收服务器信息
    chat.client.addNewMessageToPage = function (message) {
        //#chatContent就是一个div层 我们把服务器返回的信息追加到这个层上 跟QQ聊天相反,新的信息我们追加顶部
        $('#chatContent').prepend(message);
    };
    //服务器端调用的LoginUser方法,根据返回的用户列表 输出用户列表到页面上
    chat.client.LoginUser = function (UserList) {
        //在下一篇介绍的持久连接类中 是可以直接返回Json的 这里不知道怎么回事 接收的Json总是被接收成字符串 所以这里我们解析一下
        var data = eval("(" + UserList + ")");
        var html = "";
        for(var i=0;i<data.length;i++)
        {
            //这里我们做了一个判断 就是 解析用户列表Json时 如果用户的ID 就是当前用户的ID 那么就不添加 这跟QQ不一样啊 QQ中好友列表中是有自己的
            if (data[i].UserId != $("#Juser-userid").val()) {
                //如果用户的在线状态是在线呢 我们就添加onclick方法 实现 点击用户的用户 可以私聊 如果不在线 就不添加了 因为我们这个是没有存数据库的 所以没有做离线消息
                if (data[i].UserStates == "True") {
                    html += "<dl onclick=\"javascript:sendPerMessage('" + data[i].ConnectionId + "','" + data[i].UserNickName + "')\" class=\"clearfix tab-item-1\"><dt><img src=\"" + data[i].UserFaceImg + "\"></dt><dd>" + data[i].UserNickName + "</dd></dl>";
                }
                else
                {
                    html += "<dl onclick=\"javascript:void(0)\" class=\"clearfix tab-item-1 liveout\"><dt><img src=\"" + data[i].UserFaceImg + "\"></dt><dd>" + data[i].UserNickName + "</dd></dl>";
                }
            }
        }
        //更新页面用户列表
        $("#OnlineUsers").html(html);
    };
复制代码

这里注意的是服务器调用的客户端方法跟客户端写的JS方法大小写是一样的,后面我们介绍客户端调用服务器方法的时候会将 客户端调用服务器方法的时候 服务器方法的首字母是小写的,这里提醒一下。

下面是我们的发送消息的方法,当我发送消息的时候 传递我的头像和昵称给服务器 让别人显示消息的时候能显示出谁发送的(这个跟QQ消息类似啊 方便大家理解)

一个是群组消息当然也可以是全部消息,另一个是私聊,就是指定发送个某一个用户

复制代码
/// <summary>
            /// 发送消息 自定义判断是发送给全部用户还是某一个组(类似于群聊啦)
            /// </summary>
            /// <param name="groupid">接收的组</param>
            /// <param name="userfaceimg">发送用户的头像</param>
            /// <param name="usernickname">发送用户的昵称</param>
            /// <param name="message">发送的消息</param>
            public void Send(string groupid, string userfaceimg, string usernickname, string message)
            {
                if (groupid == "All")//全部用户(广播)
                {
                    //调用所有客户端的addNewMessageToPage方法 推送一条消息
                    Clients.All.addNewMessageToPage("<dl class=\"clearfix\"><dt><img src=\"" + userfaceimg + "\" /></dt><dd><i></i><div class=\"J_Users\">" + usernickname + "</div><div class=\"J_Content\">" + message + "</div></dd></dl>");
                }
                else//指定组(组播)
                {
                    //调用指定客户端的addNewMessageToPage方法 推送一条消息(所有属于组groupid的已连接用户)
                    Clients.Group(groupid).addNewMessageToPage("<dl class=\"clearfix\"><dt><img src=\"" + userfaceimg + "\" /></dt><dd><i></i><div class=\"J_Users\">" + usernickname + "</div><div class=\"J_Content\">" + message + "</div></dd></dl>");
                }
            }

            /// <summary>
            /// 发送给指定用户(单播)
            /// </summary>
            /// <param name="clientId">接收用户的连接ID</param>
            /// <param name="userfaceimg">发送用户的头像</param>
            /// <param name="usernickname">发送用户的昵称</param>
            /// <param name="message">发送的消息</param>
            public void SendSingle(string clientId, string userfaceimg, string usernickname, string message)
            {
                //首先我们获取一下接收用户的信息
                var UserInfo = UserList.Where(p => p.ConnectionId == clientId).FirstOrDefault();
                //如果用户不存在或用户的在线状态为False 那么提醒一下 发送用户 对方不在线
                if (UserInfo == null || UserInfo.UserStates == "False")
                {
                    Clients.Client(Context.ConnectionId).addNewMessageToPage("<dl  class=\"messageTip clearfix\"><dt></dt><dd>系统消息:当前用户不在线<dd></dl>");
                }
                else
                {
                    //如果用户存在并且在线呢 就把消息推送给接收的用户 并且加上当前用户信息 以及添加一个onclick事件 让接收的用户 可以直接点击消息的用户 回复 私聊信息 (不然还要在用户列表中找到谁给我发的消息 点击回复 这不科学...)
                    Clients.Client(clientId).addNewMessageToPage("<dl class=\"clearfix\"><dt onclick=\"javascript:sendPerMessage('" + Context.ConnectionId + "','" + usernickname + "')\"><img src=\"" + userfaceimg + "\" /></dt><dd class=\"per\"><s></s><div onclick=\"javascript:sendPerMessage('" + Context.ConnectionId + "','" + usernickname + "')\" class=\"J_Users\">" + usernickname + "<span>私聊</span></div><div class=\"J_Content\">" + message + "</div></dd></dl>");
                    //这句是发送给发送用户的 总不能我发送个私聊 对方收到了信息 我这里什么都不显示是吧 我也显示我发送的私聊信息 因为发送发就是我自己 所以不加onclick事件了 不允许自己跟自己聊天哦
                    Clients.Client(Context.ConnectionId).addNewMessageToPage("<dl class=\"clearfix\"><dt><img src=\"" + userfaceimg + "\" /></dt><dd class=\"per\"><s></s><div class=\"J_Users\">" + usernickname + "<span>私聊</span></div><div class=\"J_Content\">" + message + "</div></dd></dl>");
                }
            }
复制代码

这里我贴一下前台代码

复制代码
    $.connection.hub.start().done(function () {
        //用户连接时 注册一下群组和个人信息哦 这个的服务器代码 我们上面贴出来了
        //这个Demo是为了让大家理解SigalR所以没有做多复杂的流程 个人信息 我是直接传递的 
        //$("#groupid").val()这个是要注册的群组,可以自己定义 组播的时候 只要是在这一个组里的都会收到 
        //$("#Juser-login").val()这个是发送方也就是我的昵称
        //$("#Juser-faceimg").val()这个是我的头像
        //$("#Juser-userid").val()这个是我在网站中的唯一标识ID,用户连接的ID(Context.ConnectionId)也是唯一的,那么为什么还要我在这个网站中的ID呢?
        //解释一下子:单页面的聊天室是没有多大必要的,但是比如我们这个功能是放到公用里的,就像网站的在线客服一样,你总不能每个页面都写一套吧 既然是引用的这一个页面 
        //那么用户打开其他页面的时候 这个Context.ConnectionId是会变的,那我怎么知道这又是谁呢 我们就用用户在网站中的唯一标识ID作为参照,当新的连接进来时 我们看下是不是ID一样 
        //一样的话我们就更新用户列表中这个唯一标识ID用户的Context.ConnectionId和在线状态 不一样的话就添加新用户
        chat.server.group($("#groupid").val(), $("#Juser-login").val(), $("#Juser-faceimg").val(), $("#Juser-userid").val());
        $('.sendBtn').click(function () {
            //这里做一下判断 如果没有输入消息就发送 那么提示一下
            if ($('#MessageBox').val().length <= 0)
            {
                $('#chatContent').prepend("<dl  class=\"messageTip clearfix\"><dt></dt><dd>系统消息:请输入信息<dd></dl>");
            }
            else
            {
                //sendToConnectId 是我们自定义的一个字段 如果你点击了某一个用户 那么就把他的ConnectionId赋给sendToConnectId 我们知道是私聊
                //当然,用户点击退出私聊的时候 这个字段会被赋为空 表示是群聊 这个大家在Demo中一看就明白了
                if (sendToConnectId != "" && sendToConnectId.length > 0) {
                    //调用服务器私聊方法 !!!注意啊!!!服务器的私聊方法是 public void SendSingle(string clientId, string userfaceimg, string usernickname, string message)
                    //这里是chat.server.sendSingle 首字母小写啊 客户端调用的服务器方法首字母要小写  服务器调用的客户端方法 大小写一致 
                    chat.server.sendSingle(sendToConnectId, $("#Juser-faceimg").val(), $("#Juser-login").val(), $('#MessageBox').val());
                    $('#MessageBox').val("").focus();
                }
                else {
                    //这里是群聊 我们演示的没有做群组聊天 所以这里传递的是"All"表示 全部,会发送给全部用户
                    //说明一下方便理解:比如我们有这么一个情景,这个聊天是一个讨论,对某一篇文章或产品的讨论,那么是不是应该只在这篇文章或这个产品页面的用户才能收发属于这篇文章或产品消息呢,在其他页面
                    //的用户不应该能收发这里的消息呀 那么我们上面的代码chat.server.group中传递的groupid就应该是某篇文章或产品的标识,把他们划分到一个组里比如chat.server.group("A123")一个自定义字符串加上文章或产品ID,
                    //或直接用文章或产品的IDchat.server.group("123") 这里就chat.server.send("123", ...);就实现了 只有在这个页面中的用户才能收到此消息 就跟QQ的群是一样的
                    chat.server.send("All", $("#Juser-faceimg").val(), $("#Juser-login").val(), $('#MessageBox').val());
                    $('#MessageBox').val("").focus();
                }
            }
        });
    });
复制代码

使用者离线或重新连接 重写Hub的方法

复制代码
 //使用者离线
            public override Task OnDisconnected(bool stopCalled)
            {
                var UserInfo = UserList.Where(p => p.ConnectionId == Context.ConnectionId).FirstOrDefault();
                var userid = UserInfo.UserId;
                var usernickname = UserInfo.UserNickName;
                var userfaceimg = UserInfo.UserFaceImg;
                UserList.Remove(UserInfo);
                UserList.Add(new OnlineUserInfo() { UserId = userid, ConnectionId = Context.ConnectionId, UserNickName = usernickname, UserFaceImg = userfaceimg, UserStates = "False" });

                Clients.All.LoginUser(Common.JsonConverter.Serialize(UserList));
                Clients.All.addNewMessageToPage("<dl  class=\"messageTip clearfix\"><dt></dt><dd>系统消息:" + DateTime.Now.ToString("HH:mm:ss") + "&nbsp;" + usernickname + "&nbsp;离线了<dd></dl>");

                return base.OnDisconnected(true);
            }

            //使用者重新连接
            public override Task OnReconnected()
            {
                var UserInfo = UserList.Where(p => p.ConnectionId == Context.ConnectionId).FirstOrDefault();
                if (UserInfo != null)
                {
                    var userid = UserInfo.UserId;
                    var usernickname = UserInfo.UserNickName;
                    var userfaceimg = UserInfo.UserFaceImg;
                    UserList.Remove(UserInfo);
                    UserList.Add(new OnlineUserInfo() { UserId = userid, ConnectionId = Context.ConnectionId, UserNickName = usernickname, UserFaceImg = userfaceimg, UserStates = "True" });
                    Clients.All.LoginUser(Common.JsonConverter.Serialize(UserList));
                }
                return base.OnReconnected();
            }
复制代码

还有一些辅助的JS方法,在这里我就不一一贴出来了,我把demo地址留给大家 ,大家可以搭建起来研究一下。

这篇文章仅仅是个人的一些理解和实现,可能中间会出现一些不合理的地方或是错误,请大家指正,我们共同学习研究。

Demo是用VS 2013写的

下载:百度网盘

补充:Demo是我写这个博客之前写的 没有用到HubName 这个特性 所以Demo跑起来会有错误 大家删除这个特性就没有错误了 在Hubs文件夹下的ChatHub.cs

原创文章 转载请尊重劳动成果 http://yuangang.cnblogs.com

.Net 开源项目资源大全 - 特洛伊-Micro - 博客园

mikel阅读(654)

来源: .Net 开源项目资源大全 – 特洛伊-Micro – 博客园

Awesome DotNet,这又是一个 Awesome XXX 系列的资源整理,由 quozd 发起和维护。内容包括:编译器、压缩、应用框架、应用模板、加密、数据库、反编译、IDE、日志、风格指南等。

伯乐在线已在 GitHub 上发起「DotNet 资源大全中文版」的整理。欢迎扩散、欢迎加入。

https://github.com/jobbole/awesome-dotnet-cn


(注:下面用 [$] 标注的表示收费工具,但部分收费工具针对开源软件的开发/部署/托管是免费的)

API

  • 框架
    • NancyFx:轻量、用于构建 HTTP 基础服务的非正式(low-ceremony)框架,基于.Net 及 Mono 平台。
    • ASP.NET WebAPI:快捷创建 HTTP 服务的框架,可以广泛用于多种不同的客户端,包括浏览器和移动设备。
    • ServiceStack :架构缜密、速度飞快、令人愉悦的 web 服务。
    • Nelibur:Nelibur 是一个使用纯 WCF 构建的基于消息的 web 服务框架。Nelibur 可以便捷地创建高性能、基于消息的 web 服务,使得你全面拥有 WCF 的强大能力。
  • WebAPI Contrib:帮助你提高 ASP.NET Web API 能力的开源项目集合。

应用框架(Application Frameworks)

  • ASP.NET Boilerplate:现代 ASP.NET MVC web 应用程序的入门,包含最佳实践和最流行的工具。
  • Orleans:Orleans 框架提供了直接构建分布式、大规模计算应用的方法,无需学习和使用复杂的并行或扩展模型。
  • CoreFX:corefx 仓库包含了 .NET 核心功能库的实现(被称为“CoreFX”)。包含了 System.Collections、System.IO、System.Xml 以及诸多其它组件。目前构建并运行于 Windows 平台。你可以关注这个仓库,了解在未来的几个月内即将增加的对 Linux 和 Mac 的支持。
  • CSLA .NET:业务层开发框架 http://www.cslanet.com
  • Mono:Mono 是 ECMA CLI、C# 以及 .NET 的开源实现。
  • Mono-Addins:Mono.Addins 是一个通用框架,用于创建可扩展的应用程序,以及这些应用程序的扩展插件。
  • Spring.Net:Spring.NET 是一个开源的应用程序框架,可以便捷地创建企业级 .NET 项目。

应用模板(Application Templates)

  • MVC.TemplateASP.NET MVC 5 入门项目模板。
  • ProjectScaffold:F# 基金会推荐的 .NET 解决方案的原型——包括文件系统的搭建、用于管理依赖的 Paket 以及用于自动化构建、测试的 FAKE。默认情况下,构建流程也会对文档进行编译,并生成 NuGet 程序包。
  • Side-Waffle :包含大量有用的 Web 和桌面开发模板。
  • Template10 :带有设计模式的 Windows 10 模板。

人工智能(Artificial Intelligence)

  • AIMLBot(Program#):使用 C# 编写的一个小型、快速、兼容标准、易于定制的聊天机器人,基于 AIML (人工智能标记语言 Artificial Intelligence Markup Language)。
  • SIML :智能综合智能标记语言(Synthetic Intelligence Markup Language),下一代聊天机器人及数字助手语言。

程序集处理(Assembly Manipulation)

  • dnSpy:dnSpy 是一个 .NET 程序集编辑器、反编译器和调试器,来自 ILSpy 分支。
  • Fody:织入(weaving).net 程序集的可扩展工具。
  • Mono.Cecil:Cecil 类库用于生成和检查 ECMA CIL 程序和库。

资源(Assets)

  • Cassette:管理 .NET web 应用程序资源(脚本、css 和 模板)
  • NodeAssets:.net 资源管理器,通过 SignalR 实时更新 css,也可以使用 NodeJS 编译器。
  • Bundler:编译和最小化 Less、Sass、Stylus、Css、JS、CoffeeScript、LiveScript 文件。MVC集成了 MVC 和 ServiceStack。
  • SquishIt:让你轻松合并一些 css 和 JavaScript

认证和授权(Authentication and Authorization)

  • ASP.NET Identity:用于 ASP.NET 应用程序的新身份系统。
  • DotNetOpenAuth:OpenID、OAuth 和 InfoCard 协议的一个 C# 实现。
  • Logibit Hawk:一个 F# Hawk 认证库。
  • IdentityModel:.NET 4.5 和 MVC4、Web API 身份和访问控制的辅助库。
  • IdentityServer:可扩展的 OAuth2 和 OpenID 连接提供程序框架。
  • OAuth:超轻量级 OAuth 1.0a 签名生成库,C# 编写。

自动构建(Build Automation)

  • Psake:基于 .NET 的自动化构建工具,使用 PowerShell 编写。
  • FAKE:F# Make,一个跨平台自动构建系统。
  • Invoke-Build:PowerShell 自动构建和测试工具,灵感来自 Psake。
  • MSBuild:微软构建引擎(MSBuild)是 .NET 和 Visual Studio 的构建平台。
  • Cake:Cake(C# Make)使用 C# DSL 的跨平台自动构建系统。

缓存(Caching)

  • CacheCow:ASP.NET Web API HTTP 客户端和服务器端缓存实现。
  • Akavache:一个异步、持久化的键值存储。

CLI

  • Command Line Parser:Command Line Parser 类库为 CLR 应用程序提供了一套简洁的 API,用于处理命令行参数及相关任务。
  • Fluent Command Line Parser:一个简单、强类型的 .NET C# 命令行解析库,交互方式流畅易用。
  • Power Args:PowerArgs 将命令行参数转换为 .NET 对象,便于程序使用。它还提供了大量可选的扩展,例如参数校验、自动生成使用帮助、tab 补全等等。
  • UnionArgParser:针对 F# 应用程序的声明式 CLI 参数和 XML 配置解析器。

CLR

  • CoreCLR:coreclr repo 包含了完整的 .NET 核心运行时实现(称为“CoreCLR”)。它包括 RyuJIT、.NET GC、非托管代码交互(native interop)等诸多组件。它目前构建和运行于 Windows 平台。你可以关注这个仓库,了解未来的几个月内即将增加的对 Linux 和 Mac 的支持。

CMS

  • Composite C1:一个 web 内容管理系统,着重在用户体验及适应性。
  • mojoPortal:MojoPortal 是一个可扩展、跨数据库、移动友好的 web 内容管理系统(CMS)和 web 应用程序框架,使用 C# ASP.NET 编写。
  • N2CMS:开源、轻量、代码优先的 CMS,可以无缝地集成到任何 MVC 项目中。
  • Orchard:免费、开源、专注社区的项目,目标是在 ASP.NET 平台上提供应用程序和可重用组件。
  • Piranha CMS:Piranha 是一个有趣、快速、轻量级的 .NET 框架,用于开发基于 cms 附带其它功能的 web 应用程序。它基于 ASP.NET MVC 和 Web 页面创建,完全兼容 Visual Studio 和 WebMatrix。http://piranhacms.org
  • Umbraco:Umbraco 是一个免费开源的内容管理系统,基于 ASP.NET 平台构建

代码分析和度量(Code Analysis and Metrics)

  • CodeMaid:Visual studio 扩展,用于清理、挖掘和简化 C#、C++、F#、VB、PHP、JSON、XAML、XML、ASP、HTML、CSS、LESS、SCSS、JavaScript 和 TypeScript 代码。
  • StyleCop:StyleCop 使用一组风格和一致性规则,对 C# 源代码进行分析和强制性检查。
  • Gendarme:可扩展的、基于规则的工具,用于在 .NET 应用程序和类库中查找问题。
  • Metrics-Net:捕获 CLR 和应用程序级别的度量值。所以你知道它的功能。

编译器(Compiler)

  • Bridge.NET:将 C# 编译成 JavaScript 的开源编译器 http://bridge.net/
  • ClojureCLR:从 Clojure 到 CLR 的转换,是 Clojure 项目的一部分。
  • F#:F# 编译器、核心库和工具——更安全、更快、代码更好的函数式编程语言。
  • FunScript:F# 到 JavaScript 的编译器,可以通过 TypeScript 类型提供程序使用 JQuery 等 JavaScript 库。
  • JSIL:CIL 到 Javascript 的编译器 http://jsil.org/
  • Mono-basic:Visual Basic 编译器和运行时。
  • Nemerle:Nemerle 是一个 .NET 平台高级静态类型编程语言。它提供函数式、面向对象式和命令式编程语言的特性。它拥有一个简单的类似 C# 的语法和强大的元编程(meta-programming)系统。 http://nemerle.org
  • Netjs:.NET 到 TypeScript 和 JavaScript 编译器。兼容可移植类库。你甚至可以使用 EXE 文件。
  • Roslyn:.NET 编译平台(“Roslyn”)提供开源的 C# 和 Visual Basic 编译器,包含丰富的代码分析 API。它可以使用和 Visual Studio 一样的 API 来构建代码分析工具。
  • VisualFSharp:Visual F# 编译器和工具。

压缩(Compression)

  • SharpCompress:SharpCompress 是一个用于 .NET、Mono、Silverlight、WP7 的压缩类库,可以解压rar、7zip、zip、tar、bzip2 和 gzip,提供单向读取和随机文件访问 API。支持对 zip/tar/bzip2/gzip 进行写入的实现。
  • DotNetZip.Semverd:一个开源项目,提供对 ZIP 文件处理的 .NET 类库和相关工具。 (分支自 已经不再维护的 DotNetZip
  • SharpZipLib:一个 Zip、GZip、Tar 和 BZip2 的类库,完全由 C# 编写,面向 .NET 平台。

持续集成(Continuous Integration)

  • TeamCity:可以直接使用的,可扩展、面向开发人员友好的构建服务器——开箱即用[$]
  • CruiseControl.NET:一个自动化持续集成服务器,使用 .NET Framework 实现。
  • MyGet:为NuGet、NPM、Bower 和 VSIX 提供持续集成、部署、宿主程序包仓库的服务。[开源软件免费] [$]
  • AppVeyor:.NET 持续构建和部署服务。 [$] [开源软件免费]

加密(Cryptography)

  • BouncyCastle:和 .Net 的 System.Security.Cryptography 一起,在 CLR 上提供加密算法的实现。
  • HashLib:HashLib 包含了几乎所有你见过的哈希算法,它几乎支持所有东西并且非常容易使用。
  • libsodium-net:libsodium for .NET——一个安全加密库。
  • StreamCryptor :使用 libsodium 和 protobuf 对流进行加密和解密。

数据库(Database)

数据库驱动(Database Drivers)

  • MySQL Connector:完全托管的 MySQL ADO.NET 数据库提供程序、连接器。
  • Npgsql:PostgreSQL 的 .Net 数据提供程序。
  • MongoDB:MongoDB 官方 C# 驱动。
  • ServiceStack Redis:.NET 领先的 C# Redis 客户端。
  • StackExchange Redis:来自 StackExchange 的通用 redis 客户端。
  • Cassandra:DataStax 开发的 Apache Cassandra .NET 驱动程序。
  • Couchbase:couchbase 官方 .NET 客户端库,基于 Enyim memcached 客户端。
  • Firebird.NET:由C# 编写的 .NET 数据提供程序,提供对 Firebird API 的高性能原生实现。

反编译(Decompilation)

部署(Deployment)

  • Unfold:基于 Powershell 的 .net web 应用程序部署解决方案。

DirectX

  • SlimDX:为 .NET 应用程序提供的 DirectX 封装。
  • SharpDX:SharpDX 是一个开源项目,为 .Net 及所有 Windows 平台提供完整的 DirectX API,可以开发高性能的游戏、2D/3D图形渲染以及实时音频应用程序。

分布式计算(Distributed Computing)

  • Project Orleans:Orleans 框架提供了直接构建分布式、大规模计算应用的方法,无需学习和使用复杂的并行或扩展模型。由微软研究院开发。
  • Akka.net:Akka.NET 是流行的 Java/Scala 框架 Akka 的 .NET 版本。它由社区提供,与 Typesafe(原始的 Java、Scala 版本的开发商)无关。

文档(Documentation)

  • Sandcastle:Sandcastle 帮助文件生成器和 NDoc 类似。
  • SharpDox:一个 c# 文档工具。
  • Swashbuckle:向 WebApi 项目无缝地添加 swagger 文档(译者注:swagger 是一套用于生成、描述、展现 RESTful 风格 web 服务文档的框架和规范)。
  • F# Formatting:F# 和 C# 项目的文档工具,文档生成自 F# 脚本文件、Markdown 文档、内嵌 XML 或 Markdown评论。

电子商务和支付(E-Commerce and Payments)

环境管理(Environment Management)

  • DNVM:.NET SDK 管理器,一组命令行工具,用于更新和配置需要使用的运行时环境(DNX)。

ETL

  • Reactive ETL:Reactive ETL 使用 .NET 反应性扩展框架(reactive extensions) 重写了 Rhino ETL。

游戏(Game)

  • MonoGame:一个用来创建跨平台游戏的强大框架。
  • CocosSharp:CocosSharp 是 Cocos2D 和 Cocos3D API 的 C# 实现版本,可以在所有支持 MonoGame 的平台上运行。
  • Duality:Duality 是一个 2D 游戏开发框架。专注于功能的模块化,自带一个可视化编辑器。
  • Paradox:Paradox 游戏引擎。http://paradox3d.net

地理信息系统(Gis)

  • NetTopologySuite:一个 在 .NET 平台上实现快速、可靠的 GIS 系统解决方案。
  • SharpMap:一个易于使用的地图库,可以用于 web 和桌面应用程序。

Git工具(Git Tools)

  • Bonobo Git Server:Bonobo Git Server for Windows 是一个 web 应用程序,可以安装在你自己的 IIS 上,用于管理和连接你的 git 仓库。 http://bonobogitserver.com
  • GitExtensions:GitExtensions 包含资源管理器扩展、Visual Studio 2008/2010/2012/2013 插件和一个独立的 Git 仓库工具。 http://gitextensions.github.io/
  • GitLink:让用户可以单步调试托管在 GitHub 或 BitBucket 上的代码。
  • GitVersion:根据你的 Git 仓库的状态生成一个语义化版本号(Semantic Version Number)。
  • LibGit2Sharp:LibGit2Sharp 带来了 libgit2 所有的功能和速度,是一个本地 Git 实现,可以运行在 .Net 和 Mono 平台。
  • NGit:NGit 是 JGit 移植到 C# 的版本。
  • posh-git:Git 的 PowerShell 环境。

图形(Graphics)

  • Oxyplot:OxyPlot 是一个 .NET 跨平台绘图库。
  • OpenTK:Open Toolkit 是一个封装了 OpenGL、OpenCL 和 OpenAL 的 高级底层 C# 开发库。
  • NGraphics:NGraphics 是一个 .NET 跨平台矢量图形渲染库。

GUI

  • MahApps.Metro:用于创建 Metro 风格 WPF 应用的工具箱。
  • Callisto:用于 Windows 8 XAML 应用的控件工具箱。包含若干 UI 控件,让你更容易地创建符合 Windows UI 风格规范的Windows 商店应用。
  • ObjectListView:ObjectListView 使用 C# 封装了 .NET 的 ListView 控件。它使得 ListView 更加易用,并且加入了一些新特性。
  • DockPanelSuite :灵感来自 Visual Studio 的停靠窗口(docking)类库,用于 .NET WinForm 应用。
  • AvalonEdit :在 SharpDevelop 中使用,基于 WPF 的文本编辑器组件。
  • XWT:跨平台 UI 工具箱,用于创建 .NET 和 Mono 桌面应用程序。
  • Gtk#:Gtk# 是 Gtk+ GUI 工具箱的 Mono/.NET 版本,绝大多数 Mono 中的 GUI 应用都基于它构建。
  • MaterialDesignInXamlToolkit:用于创建 Material Design 风格 WPF 应用的工具箱。
  • Eto.Forms:跨平台的 GUI 框架,用于 .NET 和 Mono 下的桌面和移动应用程序。
  • Dragablz:可拖拽、可分离(tearable,译者注:即拖拽标签页成为独立窗口)的 WPF 标签页控件(类似 Chrome)。支持布局和主题,包含兼容 MahApps 和 Material Design 的主题。
  • Fluent.Ribbon:Fluent Ribbon Control Suite 是一个在 WPF 中实现 Office 和 Windows 8 风格的 Ribbon 库。

HTML 和 CSS(HTML and CSS)

HTTP

  • Http.fs[F#] 中的一个函数式 HTTP 客户端。
  • RestSharp:.NET 下简单的 REST 和 HTTP API 协议客户端。
  • EasyHttp:C# Http开发库。
  • Refit :Xamarin 和 .NET 下自动生成强类型的 REST 库。
  • RestEase:类型安全且易于使用的 REST API 客户端库,简单可定制。大部分灵感来自 Refit。

IDE

图像处理(Image Processing)

  • ImageResizer:在图片 URL 后面增加命令,在几毫秒内获取修改后的版本,支持实时的对图片进行缩放、编辑。
  • ImageProcessor:开源 .NET 库,用于实时处理图片。
  • DynamicImage:高性能开源图片处理库,用于 ASP.NET。
  • MetadataExtractor:从图片中提取 Exif、IPTC、XMP、ICC 等其它元数据信息。
  • Emgu CV:OpenCV 的 .NET 跨平台封装。

安装工具(Install Tools)

  • Wix Toolset:强大的工具集,用于创建你自己的 Windows 安装程序。
  • Squirrel:Squirrel 即是一套工具也是一个类库,可以无安全管理 Windows 桌面程序的安装和更新。

国际化(Internationalization)

  • i18n:ASP.NET MVC 智能国际化工具。

互操作(Interoperability)

  • CefSharp:Chromium Embedded Framework 的 .NET 支持(WPF 和 WinForm)。
  • CppSharp:在 C# 中平滑使用 C++ API 的工具。
  • Sharpen:Sharpen 是 db4o 编写的 Eclipse 插件,可以让你把 Java 项目转换为 C#。
  • CXXI:C++ 互操作框架。

IoC

  • Castle Windsor:Castle Windsor 是一个用于 .NET 和 Silverlight 的成熟的 控制反转(IoC) 容器。
  • Unity:轻量级、可扩展的依赖注入容器,支持构造函数、属性和方法调用注入。
  • Autofac:令人着迷的 .NET IoC 容器。
  • Ninject:.net 依赖注入的忍者。
  • StructureMap:.Net 最早的 IoC/ID 容器。
  • Spring.Net:Spring.NET 是一个开源应用程序框架,可以便捷地创建企业级 .NET 应用。
  • LightInject :一个超轻量级 IoC 容器。
  • TinyIoC:单文件、简单、跨平台的 IoC 容器。

日志(Logging)

  • Essential Diagnostics:为内置System.Diagnostics 命名空间扩展功能,提供更灵活的日志功能。
  • NLog:先进的 .NET 和 Silverlight 日志工具。
  • ELMAH:ELMAH 官方网站
  • Elmah MVC:MVC 版 Elmah。
  • Logary:Logary 是一个 mono 和 .Net 平台下高性能、多目标的日志、度量、追踪和健康检查库。支持多目标,为微服务构建。
  • Log4Net:Apache log4net 工具库能够帮助程序员向多种不同的目标输出日志语句。
  • Serilog:一个 NoSQL 时代下简单直接的日志库。将多个优秀的传统结构化分析日志功能合并到一个易于使用的程序集中。
  • StackExchange.Exceptional:Stack Exchange 网络使用的错误处理程序。
  • Semantic Logging Application Block (SLAB):为内置 System.Diagnostics.Tracing 命名空间(EventSource类)扩展功能,支持将日志记录到多个容器中,包括 Azure 表存储、数据库、文件(JSON、XML、文本文件)。通过 ETW 支持进程内和进程外的日志记录,支持 Rx 进行实时的事件过滤和聚合。

机器学习和数据科学(Machine Learning and Data Science)

  • Accord.NET:机器学习框架,包含了音频和图像处理的库(计算机视觉、计算机听觉、信号处理和统计)。
  • Accord.NET Extensions:高级图像处理和计算机视觉算法扩展。
  • AForge.NET:为计算机视觉和人工智能领域的开发者和研究人员提供的框架(包括图像处理、神经网络、遗传算法、机器学习、机器人科学)。
  • Deedle:处理探索性数据的数据帧和时序库,支持 C# 和 F#。
  • FsLab:数据科学和机器学习库的集合,支持 F# 和 .NET。
  • numl :包含最流行的监督学习和无监督学习算法,尽量减少创建预测模型时的冲突。
  • R Provider :将 R 语言包和函数封装为类型安全的类型提供程序供 F# 调用。
  • F# Data:F# 类型提供程序,访问 XML、JSON、CSV 和 HTML 文件(基于样例文档),以及 WorldBank 数据。

Markdown 处理(Markdown Processors)

  • MarkdownSharp:C# 实现的开源 Markdown 处理器,在 Stack Overflow 中使用。
  • F# Formatting:用于生成 F# 和 C# 项目文档的工具。该工具库的核心组件中包含了可扩展的 Markdown 解析器。
  • CommonMark.NET:CommonMark 规范的 C# 实现,用于将 Markdown 文档转换为 HTML。为最佳性能和可移植性进行了优化。

邮件(Mail)

  • FluentEmail:System.Net.Mail 的一个流式(Fluent)封装,支持 razor 模板引擎。
  • MailKit:完整的跨平台的邮件协议栈,包括 IMAP、POP3、SMTP,支持验证等特性。基于 MimeKit 构建。
  • MimeKit:跨平台 .NET MIME 创建和解析库,支持 S/MIME、PGP、TNEF 和 Unix mbox spools。
  • PreMailer.Net:一个 C# 开发库,将你的样式表嵌入到内置的 style 属性中,最大限度支持邮件客户端。

数学(Mathematics)

  • MathNet:Math.NET 是一个开源项目,旨在创建和维护涵盖基础数学在内的工具集,面向高级和日常需要使用此类功能的 .Net 开发人员。

多媒体(Media)

  • TagLib#:TagLib#(即 taglib-sharp)是一个读写媒体文件元数据的库,支持视频、音频和照片格式。

度量(Metrics)

微框架(Micro Framework)

  • .NET Micro Framework Interpreter:Microsoft® .NET Micro Framework(NETMF)是一个在 Visual Studio 中提供为小型设备上编写嵌入式应用的框架。

杂项(Misc)

  • .NET Fiddle:在浏览器中编写、编译并运行 C# 代码。相当于 C# 版本的 JSFiddle。
  • AzureCrawler:从 Angular、Ember、Durandal 或任何 JavaScript 应用中获取 HTML 快照。
  • BitSharp:C# 比特币节点。
  • CSScript:CS-Script 是一个基于 CLR 的脚本系统,使用 C# 作为编程语言。CS-Script 目前针对微软的 CLR 实现(.NET 2.0/3.0/3.5/4.0/4.5)并完整支持 Mono。附带很多附加特性,比如脚本宿主。
  • CsvHelper:帮助读写 CSV 文件的开发库。http://csvhelper.com
  • FluentValidation:一个小型的 .NET 校验库,使用流式接口和 lambda 表达式构建校验规则。
  • Humanizer:Humanizer 能够在 .NET 平台上满足所有针对字符串、枚举、日期、时间、时间范围、数字等类型数据的操作和显示要求。
  • LINQPad:一个 C#/VB/F# 的便签本,能够立即执行任何表达式、语句块或程序,带有富文本显示等有用的特性。同样可以让你使用 LINQ 进行交互性数据库查询。 [$](译者注:也有免费许可,但是功能受限)
  • Polly:快捷便利的异常处理策略,例如 重试、始终重试、等待并重试或断路(Circuit Break)等行为。 (.NET 3.5、4.0、4.5、PCL、Xamarin)
  • Rant:Rant 程序文本生成 DSL(领域特定语言)。 http://berkin.me/rant
  • ScriptCS:使用文本编辑器、nuget 和强大的 Roslyn 来编写 C# 应用!

MVVM

  • Caliburn.Micro :小型但功能强大的框架,可以用来给所有 XAML 平台创建应用。它对 MV* 模式的强大支持可以让你快速构建你的解决方案,与此同时不必牺牲代码质量和可测试能力。
  • MVVM Light Toolkit:该工具箱主要是用来加速创建和开发 MVVM 应用,适用于 WPF、Silverlight、Windows Store(RT)和 Windows Phone 平台。
  • Catel:Catel 是一个应用开发平台,主要着眼在 MVVM(WPF、Silverlight、Windows Phone 及 WinRT)以及 MVC(ASP.NET MVC)。Catel 的核心部分包含 IoC 容器、模型、校验、备忘录模式(memento)、消息中介(message mediator)、参数检查等。
  • UpdateControls:Update Controls 不需要你实现 INotifyPropertyChanged 接口或声明一个 DependencyProperty。可以将控件直接关联到 CLR 属性,这使得它完美贴合 MVVM 模式。
  • ReactiveUI:一个 .NET 下的 MVVM 框架,集成了反应性扩展框架(Rx),允许开发者使用 WPF、Windows Store Apps、WP8 或 Xamarin 创建优雅的、可测试的应用。
  • Okra App Framework:一个以 app 为中心的 Windows 8.1 MVVM 框架,融合依赖注入,包含一套完整的 Visual Studio MVVM 模板。
  • WPF Application Framework (WAF):一个轻量级的框架,能够帮助你创建结构优雅的 WPF 应用。支持你使用分层架构和 MVVM 模式。
  • MVVMCross:跨平台mvvm 移动开发框架,针对 WP7 和 WP8 的 WPF/Silverlight、Android 的 Mono、iOS 的 MonoTouch 以及 WPA8.1/Windows 8.1 商店应用的 Windows Universal 项目。它使用可移植类库(PCL)来支持可维护的跨平台 C# 原生应用。
  • Stylet:最小化 MVVM 框架(参考 Caliburn Micro),包含了良好的文档、高覆盖率的测试以及自带的 IoC 容器。
  • Gemini:类似 Visual Studio Shell 的 IDE 框架。基于 WPF、AvalonDock 和 Caliburn Micro 构建。

Office

  • ClosedXML:ClosedXML 能够让开发人员更便捷地创建 Excel 2007、2010 文件。
  • NPOI:该项目是 .NET 版本的 POI 项目,原始的 Java 版本位于http://poi.apache.org/ 
  • EPPlus:EPPlus 是一个 .net 类库,用于读写 Open Office Xml 格式的 Excel 2007、2010 文件(xlsx)。
  • Open XML SDK:Open XML SDK 是一个开源库,用于处理 Open XML 文档(包括 DOCX、XLSX 和 PPTX)。

ORM

  • Entity Framework:对象关系映射器(ORM)框架,让 .NET 开发人员使用领域特定的对象来处理关系型数据。
  • BL Toolkit:.NET 平台的业务逻辑工具箱。
  • Dapper:一个超小型、快捷轻便的 ORM 框架。
  • Dapper Extensions:小型类库,对 Dapper 的功能进行补充,为你的简单传统 CLR 对象提供基础的 CRUD(Get、Insert、Update、Delete) 操作。
  • NHibernate:NHibernate 对象关系映射器(移植自 Java 平台的 Hibernate)。
  • Fluent NHibernate:便捷、无需使用 XML、编译安全、自动化、基于约定命名的 NHibernate 映射库。
  • FluentMigrator:.net 下的便捷的迁移框架。
  • ServiceStack.OrmLite:轻量、简单、快速、基于命名约定的 POCO ORM。
  • Massive:小型、令人愉悦的数据访问工具,始终关爱你直到永远。
  • LINQ to DB:最快的 LINQ 数据库访问库,简单、轻量、快速、类型安全,在你的对象(POCO)和数据库之间搭建桥梁。

包管理(Package Management)

PDF

  • ITextSharp:iText 是一个PDF库,用于创建、修改、检查和维护 Portable Document Format(PDF)格式的文档 [$]**[开源软件免费]**

Profiler

推送通知(Push Notifications)

  • PushSharp:服务器端的推送通知类库,支持 iOS、OSX、Android、Chrome、Windows Phone、Windows 8、Backberry 和 Amazon 设备。

队列(Queue)

  • NServiceBus:.NET 平台下最流行的服务总线。
  • Hangfire:在 ASP.NET 应用中,超简单地实现自主引导(fire-and-forget)、延迟和周期重复任务。
  • RabbitMQ.NET:AMQP 客户端的 C# 实现,通过 WCF 绑定到已有的 AMQP 服务。
  • NetMQ:NetMQ 是 ZeroMQ 纯 C# 移植版本。
  • MassTransit:MassTransit 是一个精简服务总线(lean service bus)的实现,使用 .NET Framework 来构建松耦合应用程序。
  • Rebus:Rebus 是一个 .NET 平台的精简服务总线和 NServiceBus、MassTransit类似,只不过更加精简。
  • EasyNetQ:易于使用的 RabbitMQ .NET API。
  • Warewolf ESB:易于使用的服务总线和微服务平台,可以在一个可视化 IDE 中便捷的创建应用和服务。

响应式编程(Reactive Programming)

  • Rx.NET:Reactive Extensions (Rx)库使用观察者序列(observable sequences)和 LINQ 风格的查询操作,来进行异步和基于事件的程序开发
  • Dynamic Data:用于集合的响应式编程框架。

计划调度(Scheduling)

  • QuartzNet:Quartz 是 .NET 平台的企业级调度器。

SDK 和 API 客户端(SDK and API Clients)

  • AWS SDK:AWS SDK for .NET 让 .NET 开发者可以便捷地操作 Amazon Web Services。
  • Azure PowerShell:一组 PowerShell 命令行,让开发者和管理员开发、部署和管理 Microsoft Azure 应用。
  • Octokit.NET:.NET 平台下的 GitHub API 客户端库。
  • DropNet:Dropbox API 客户端开发库。

搜索(Search)

  • Elasticsearch .NET:Elasticsearch.Net & NEST。
  • PlainElastic.Net:ElasticSearch 的一个简单的 .Net 客户端。
  • SolrNet:.Net 平台下的 Solr 客户端。
  • Lucene.net:Lucene.Net 是 Lucene 搜索引擎库的移植,使用 C# 编写,面向 .NET 环境的用户。

序列化(Serialization)

  • Protobuf.NET:Protocol buffers 是 Google 使用的二进制序列化格式,在 Google 数据通讯中大量使用。
  • Json.NET:.NET 平台下流行的、高性能 JSON 框架。
  • ServiceStack.Text:在 servicestack.net 中使用的 JSON、JSV、CSV 文本序列化器。
  • Msgpack-Cli:MessagePack 的 CLI 实现。
  • Jil:.NET 平台下快速的 JSON 序列化器,基于 Sigil (在 StackOverflow 中使用)。
  • ProtoBuf:根据 .proto 规范,为 protocol buffer 序列化内容生成 C# 代码。
  • F# Data:F# 类型提供程序,访问 XML、JSON、CSV 和 HTML 文件(基于样例文档),以及访问 WorldBank 数据。
  • Bond:跨平台框架,用于处理系统化(schematized)数据。支持跨平台的序列化、反序列化,以及强大的通用机制来高效处理数据。

状态机(State machines)

  • Stateless:直接使用 .NET 代码创建一个状态机和轻量的基于状态机的工作流。
  • Automatonymous:.Net 平台的状态机库,允许你编写流式API风格的状态机。

静态网站生成(Static Site Generators)

  • Pretzel:.NET 平台下的网站生成工具(包含后续的一些功能)。
  • Sandra.Snow:.NET 平台的静态网站生成工具,借鉴 Jekyll。
  • Wyam:简单易用、高度模块化、拥有强大配置能力的静态网站生成工具。

风格指南(Style Guide)

模板引擎(Template Engine)

  • RazorEngine:基于微软 Razor 解析器引擎的开源模板引擎。
  • Nustache :无逻辑模板的开源库。
  • DotLiquid:Ruby Liquid 模板语言的 C# 移植版本。

测试(Testing)

  • AutoFixture:AutoFixture 是一个用于 .NET 的开源框架,用于简化单元测试中的设置(Arrange)阶段。
  • FakeItEasy:.NET 平台的一个简单的 mocking 库。http://fakeiteasy.github.io
  • Fluent Assertions:一组 .NET 扩展方法,可以让你更自然地指定 TDD 或 BDD 风格测试的期望值。
  • Fuchu:F# 的单元测试库,通过 tests-as-values 机制让你更容易创建领域特定语言(DSL)。
  • Machine.Specifications:Machine.Specifications (MSpec)是一个上下文、规范框架,忽略了语言本身的干扰,简化了测试。
  • Moq:.NET 平台下最流行和友好的 mocking 框架。
  • NBuilder:快速创建测试对象。
  • NSubstitute:一个友好的 .NET mocking 框架。
  • NUnit
  • Rhino Mocks:.NET 平台的动态 Mocking 框架
  • Shouldly:Shouldly 是一个断言(assertion)框架,主要功能是在断言失败时,给出简单明了并且友好的错误信息。
  • SpecFlow:将业务需求绑定到 .Net 代码。
  • xUnit:xUnit.net 是一个 .NET 平台下免费、开源、专注社区的单元测试框架。

交易(Trading)

Visual Studio 插件(Visual Studio Plugins)

  • Web Essentials:Web Essentials 为 Visual Stduio 扩展了大量的特性,提供了 web 开发人员盼望多年的功能。
  • VsVIM:Visual Studio 中的 VIM。
  • Nuget Package Manager:NuGet 是微软开发平台(包括 .NET)的包管理器。
  • SideWaffle:Visual Studio 2012、2013 中的一组项目模板集合,让 web 开发人员更加轻松。
  • Resharper:Visual Studio 开发人员生产力工具 [$]
  • Refactoring Essentials:开源 C# 和 VB.NET 重构扩展,包括代码最佳实践分析器。
  • CodeContracts:.NET CodeContracts 工具源代码。
  • Git Diff Margin:在 Visual Studio 滚动条区域实时显示当前文件在 Git 上的差异。
  • Productivity Power Tools:一组 Visual Studio 专业版(及更高版本)的扩展,用于提高开发人员的生产力。

Web 框架(Web Frameworks)

  • ASP.NET MVC:ASP.NET 是一个免费的 web 框架,用于创建优秀的 web 站点和应用程序。
  • FubuMVC:.NET 平台下前端控制器(front-controller)风格的 MVC 框架。http://fubuworld.com/fubumvc
  • NancyFx:在 .Net 和 Mono 平台上创建 HTTP 服务的一个轻量级、非正式的框架。
  • IISNode:在 IIS 中宿主 NodeJS 应用程序。
  • Suave.IO:一个框架/库/web 服务器,当你看到你使用优美的 F# 编写的代码提前完成了你的项目时,它的存在会让你喜极而泣。(一个用 F# 编写 Web 应用的框架和服务器端)

Web 服务器(Web Servers)

  • EmbedIO :基于 Mono 编写的跨平台的 Web 服务器。
  • XSP:Mono 中的 ASP.NET 宿主服务器。该模块包含了 Apache 模块、FastCGI 模块,可以用于挂载到其它 web 服务器或是作为一个测试用的独立服务器存在(类似微软的 Cassini 项目)。

WebSocket

  • SignalR:ASP.NET 库,开发者可以通过它在 web 应用程序中非常简单地实现实时功能。
  • Fleck:Fleck 是一个 C# 实现的 WebSocket 服务器。分支自 Nugget 项目。
  • Websocket-Sharp:WebSocket 协议的 C# 实现,包含客户端和服务器端。
  • XSockets:提供了一组工具,可以在微软 .NET 等平台上构建一个实时应用程序。
  • WebSocket4NET:.NET 2.0+、Xamarin、Mono、Silverlight、Windows Phone 以及 WinRT 下的 WebSocket 客户端。

Windows 服务(Windows Services)

  • TopShelf:一个简单的服务宿主框架,使用 .NET 构建 Windows 服务。

其他列表(Other Lists)

Git基础概念与Flow流程介绍 - 陈晨_软件五千言 - 博客园

mikel阅读(847)

来源: Git基础概念与Flow流程介绍 – 陈晨_软件五千言 – 博客园

本文会分为两部分讲解,第一部分介绍Git的基础概念、常见客户端、常用命令,是一个基础说明。第二部分介绍Git的管理流程,主要是GitFlow,Github Flow、Gitlab Flow和ExeFlow四种。

Git相关

基本概念

Git是一个基于GNU协议的开源分布式版本控制系统,是由Linux的创始人Linus Torvalds在2005为了进行Linux内核的研发时自己编写的。不同于之前的大部分客户端-服务器模式的代码管理系统,在每台电脑上的每个Git目录都是一个完整的代码仓库,包含了历史所有的提交记录并且可以完整查看所有版本,而不需要有服务器或者网络连接。
2019年9月Git的当前的最新版本为2.23.0.

常见客户端

TortoiseGit

TortoiseGit,就是我们俗称小乌龟。他们为Svn也提供了很优秀的windows客户端。而且这是一个开源的软件,当前最新的版本位2.8.0 。
安装之后会自动注入系统的右键菜单,在任何路径右击之后都会出现

如图的选项,这是在非git仓库时。当在git仓库右键点击时完整菜单如下

查看提交记录

Sourcetree

Sourcetree是Atlassian提供的一款免费的Git客户端工具,目前的版本是3.2.6。
安装之后直接打开客户端使用,整体界面大致如图。

Intellij Idea

Idea是Java开发非常热门的IDE,其中也集成了多种SCM工具,自然也包括Git的客户端,整体的使用感受还是不错的。

命令行

最后名不符实的再加上一个命令行吧,有很多同学还是习惯手敲命令的。

常用命令

存储区域

Git主要有四块存储区域:

  • Workspace:工作区
  • Index / Stage:暂存区
  • Repository:仓库区(或本地仓库)
  • Remote:远程仓库
    工作区是本地计算机存储,平时项目代码存储的地方。
    暂存区也是在本地存储,当你在修改代码但是还没有执行commit操作时临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息。
    仓库区就是本地版本库,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本。
    远程仓库就是比如Gitlab或者Github等。
    几个存储区域之间的工作流程一般是这样:

还有另外一个版本的流程:

命令之 add & commit &push

add & commit 实际上就是一个文件加入版本控制的过程,在受git管理的目录下新建一个文件,首先要将它标记为add,接下来commit到本地的仓库,就完成了本地的版本管理。
之后可以选择是否执行push操作,如果执行就是将本地的变更提交到远程服务器上,这样别人就可以获取到你的更新了。

命令之 branch & checkout

branch是常见的创建分支应用的语法,git和传统的cs模式的SCM的工具相比branch的代价是非常小的,影响也是非常小的。git的branch可以只存在与本地,轻易和合并与删除。

上图就是很多Flow流程中可能存在的多个分支(实际上这些分支本地和远程都是存在的)。
我们本地的一个项目可能就会存在多个分支,我们使用checkout命令,签出一个分支之后,环境中的文件都会变为该分支的相关文件。

命令之 cherry-pick

pick是挑选的意思,我们看一下示意图

这是要求将 bugFix 分支上的 C3 、side 分支上的 C4 以及another分支上的C7通过cherry-pick的形式拿到 master分支上。这是很典型的一个使用cherry-pick的场景,bug修复的合并。

命令之 merge & rebase

通过上面的branch和push,我们已经切出不同的分支并且提交了,接下来就是要合并我们的提交内容到主分支上,这时我们可能会面临两个命令选择 merge和rebase。
这两个命令有什么区别呢?我们通过一个模拟界面来看一下:
使用merge命令

使用rebase命令

建议:
rebase会把你当前分支的 commit 放到公共分支的最后面,所以叫变基。就好像你从公共分支又重新拉出来这个分支一样。
merge 会把公共分支和你当前的commit 合并在一起,形成一个新的 commit 提交。
为什么建议使用rebase,因为通常我们是feature分支基于master分支进行rebase,master是长期固定分支,feature是临时分支,我们不希望因为临时分支的变更影响到master分支的提交记录,而且通常情况下master分支是锁定不允许直接提交的。所以建议大家使用rebase,这样能够在不影响master分支的情况下还能够合并最新的内容。

Flow相关

我们这里主要讲四种flow进行对比,GitFlow,GitHub Flow,GitLab Flow,ExeFlow
我对于项目管理的核心理解有两点:

  • 需求边界
  • 时间边界
    也就是一次迭代,就是在规定的时间边界与规定的需求边界范围内完成。如果两方面都能够保质保量,自然没有问题。其实那种Flow我觉得差异不算很大。但是当其中有一点无法满足时,不同的Flow能够达到的效果就不同了。这点自然是不同的企业有不同的场景与要求,有的企业可以拖延时间(工期),但是一定要保证规划内的需求全部开发测试完成。有的公司则是对时间节点的要求更高,可以减少某些需求,但是一定要在规定时间点发布上线。我们在理解每种flow时,也会对项目管理的两点影响说明一下。

GitFlow

GitFlow来源应该是 Vincent Driessen 在2010年1月发表的这篇《A successful Git branching model》,基本是现在Git中最出名的流程管理方法了。

我整理了其对应的流程图,其中加粗的是指长期分支。可以看到master和develop是其中的长期分支,对外的发布基于master分支,对内的研发基于develop分支。需要发布版本时,是从develop分支切出release分支,最终合并至master。所以我理解在GitFlow中,最重要的实际上是develop分支,它承载了实际功能的开发修正和发布,而master最大的作用有两个,一是发布,二是热修正(hotfix)。
GitFlow的流程我理解时偏重时间,而非需求的。也就是说如果临近发布时间,而需求没有完成,其唯一的选择就是延期,因为按照流程,release分支是从develop分支切出,如果测试的环境是基于develop,很可能是没有打到发布标准的,所以只能等打到发布标准后才能进行后续步骤。但是好处在于开发只用基于develop分支,很难出现漏合并代码或者bug修正之类的情况。我也觉得这份流程在大型企业内部是比较难推进的,因为它的环境管理还不够,它的release、master分别对应预发布和正式环境,develop我觉得还不够清晰,因为这块我们通常是需要两个环境,开发和测试环境。所以对于多环境管理我觉得是需要根据不同的企业的要求进行改造的。

GitHub Flow

顾名思义,GitHub Flow就是GitHub推荐的管理流程

可以看到,只能用简单2字形容,只有master和feature两个分支概念,其中master是长期分支。所以我还加上了Github官方的一些说明。
我觉得这不是一份可以用于企业级复杂项目管控的Git 流程,最基础的就是没有多环境管理,无法想象多角色配合时只基于master分支如何进行。master究竟用于测试环境还是随时可发布的正式环境呢?其次这份流程应该也是偏重于需求而非时间。理由和GitFlow一样。
我觉得GitHub推出的这份flow主要是应用于其平台上大部分托管的小型开源项目,并且尽量结合平台提供的其他组件。对于企业内部不够合适。

GitLab Flow

GitLab Flow自然是基于GitLab环境的flow管理流程

这个Flow实际上最核心的分支是基于master,生产环境是production,预发布环境是pre-production。我觉得对于多环境的问题实际上和GitFlow很相似,也是开发和测试环境不够清晰。
提交、审核基于GitLab的MR进行。截图的部分就是GitLab官方的MR的说明。
GitLab Flow与GitFlow的差别我觉得仅仅在于master与develop的分支命名,还有就是加入了MR(但是由于GitFlow不基于任何服务端环境,所以这块是可以整合的),问题也很相似。

ExeFlow

由于上面几种Flow在时间和需求都是选择了需求而延迟了时间,我也顺便讲一下选择时间而放弃一些需求的Flow流程吧。
这是我之前一家公司的流程设计,服务端是GitLab。
实际工作场景:
我们的系统由于主要是面向大型企业内部使用,存在复杂的分发流程和权限控制,经过长时间的累积业务模型也很复杂各种关联和引用,所以有一些大型任务的开发周期可能会比较长,到达2-3个月的周期。
我们的迭代周期正常是1个月。流程大概如下:

  • 上月末进行迭代计划评估与安排,这里会确认下月迭代目标的Story内容与数据。各自主管进行子任务的拆分评估与排期。
  • 开发时间一般是2周,我们基本是会在月中设定研发截止线,所有研发任务要在截止线前完成提测。期间有完成的任务可以随时提测。【涉及分支:Feature,Local,Develop】
  • 完整的系统集成测试时间一般是安排在第三周,测试会进行全面的测试。本周研发的主要任务一方面是处理Bug,一方面可以介入下月迭代大项的需求说明与分析。【涉及分支:Feature,Local,Develop】
  • 第四周的前三天,我们会切出预发布的分支在第四周周一时,会给出明确本次能够上线的Story List,不在清单内的都不允许合并只预发布环境(也就是我们实际上运行需求在预发布之前仍旧有变更,只要测试人员通过了集成测试环境,就可以合并并且发布),本次发版的具体内容和通知也是当天发出。【涉及分支:Feature,Release】
  • 发版一般安排在当月的最后一个周四(为了防止有线上问题,所以不能是周五第二天会没有人员值守)。【涉及分支:Release,Master】

流程图:

这里有几个特点:

  • develop对于测试环境,local对应开发联调环境。
  • 所有的分支起始时都是由master分支切出
  • 固定长期分支有三个:master,develop,local
  • 所有的分支不能直接向master提交,必须通过release验证后合并至master。
  • master分支锁定需要权限审核提交
  • release是临时分支,指定时间从master切出,直接从feature合并。

先来说说有点,根据之前提供的流程来看,我们企业要求的是时间保障而需求可以调整。所以在指定时间节点到来时,我们会确定一份可以发布的需求清单,根据这份清单来合并至release,从而最终能够发布。这是一个比较典型的保时间点,放需求的流程管理。
但是这个会有下面几个问题:

  • develop和local分支从master切出后,长期和master不同步,所以需要定期的rebase,否则会产生很多环境不一致导致的问题。
  • hotfix或者feature提交之后的bug修正,都是需要提交最多三个分支的。研发人员的操作会非常复杂。

但是由于这个流程解决了我们实际生产流程中的问题,所以整体在控制和配合上带来的收益远大于我们的障碍。所以这套流程还是长期推广了起来。

总结

Git是一个工具,Flow是一套管理流程。最重要的并不是我们在用什么,而是我们解决了什么问题?我们试图解决的问题到底是不是真实的问题,还是我们一厢情愿臆想出来的。整个过程,实际上是我们针对企业的环境和问题进行发掘的解决的过程,而不是单纯挑选工具和流程的过程。
记得先问自己,我现在到底要解决的是什么问题?

WebSocket在ASP.NET MVC4中的简单实现 - 小白哥哥 - 博客园

mikel阅读(907)

来源: WebSocket在ASP.NET MVC4中的简单实现 – 小白哥哥 – 博客园

WebSocket 规范的目标是在浏览器中实现和服务器端双向通信。双向通信可以拓展浏览器上的应用类型,例如实时的数据推送、游戏、聊天等。有了WebSocket,我们就可以通过持久的浏览器和服务器的连接实现实时的数据通信,再也不用傻傻地使用连绵不绝的请求和常轮询的机制了,费时费力,当然WebSocket也不是完美的,当然,WebSocket还需要浏览器的支持,目前IE的版本必须在10以上才支持WebSocket,Chrome Safari的最新版本当然也都支持。本节简单介绍一个在服务器端和浏览器端实现WebSocket通信的简单示例。

1.服务器端

我们需要在MVC4的项目中添加一个WSChatController并继承自ApiController,这也是ASP.NET MVC4种提供的WEB API新特性。

在Get方法中,我们使用HttpContext.AcceptWebSocketRequest方法来创建WebSocket连接:

namespace WebSocketSample.Controllers
{
    public class WSChatController : ApiController
    {
        public HttpResponseMessage Get()
        {
            if (HttpContext.Current.IsWebSocketRequest)
            {
                HttpContext.Current.AcceptWebSocketRequest(ProcessWSChat);
            }
            return new HttpResponseMessage(HttpStatusCode.SwitchingProtocols);
        }

        private async Task ProcessWSChat(AspNetWebSocketContext arg)
        {
            WebSocket socket = arg.WebSocket;
            while (true)
            {
                ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[1024]);
                WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
                if (socket.State == WebSocketState.Open)
                {
                    string message = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);
                    string returnMessage = "You send :" + message + ". at" + DateTime.Now.ToLongTimeString();
                    buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(returnMessage));
                    await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
                }
                else
                {
                    break;
                }
            }
        }
    }
}

在这段代码中,只是简单的检查当前连接的状态,如果是打开的,那么拼接了接收到的信息和时间返回给浏览器端。

2.浏览器端

在另外一个视图中,我们使用了原生的WebSocket创建连接,并进行发送数据和关闭连接的操作

@{
    ViewBag.Title = "Index";
}
@Scripts.Render("~/Scripts/jquery-1.8.2.js")

<script type="text/javascript">
    var ws;
    $(
        function () {
            $("#btnConnect").click(function () {
                $("#messageSpan").text("Connection...");
                ws = new WebSocket("ws://" + window.location.hostname +":"+window.location.port+ "/api/WSChat");
                ws.onopen = function () {
                    $("#messageSpan").text("Connected!");
                };
                ws.onmessage = function (result) {
                    $("#messageSpan").text(result.data);
                };
                ws.onerror = function (error) {
                    $("#messageSpan").text(error.data);
                };
                ws.onclose = function () {
                    $("#messageSpan").text("Disconnected!");
                };
            });
            $("#btnSend").click(function () {
                if (ws.readyState == WebSocket.OPEN) {
                    ws.send($("#txtInput").val());
                }
                else {
                    $("messageSpan").text("Connection is Closed!");
                }
            });
            $("#btnDisconnect").click(function () {
                ws.close();
            });
        }
    );
</script>

<fieldset>
    <input type="button" value="Connect" id="btnConnect"/>
    <input type="button" value="DisConnect" id="btnDisConnect"/>
    <hr/>
    <input type="text" id="txtInput"/>
    <input type="button" value="Send" id="btnSend"/>
    <br/>
    <span id="messageSpan" style="color:red;"></span>
</fieldset>

3.测试结果

image

英文原文链接

C#使用VS2019打包安装程序(图标修改和默认安装路径修改) - qq_41487299的博客 - CSDN博客

mikel阅读(2024)

来源: C#使用VS2019打包安装程序(图标修改和默认安装路径修改) – qq_41487299的博客 – CSDN博客

这次主要是记录一下我在C#打包时遇到的一些坑。
环境:Vs2019+C#
要打包安装程序,第一件事就是去扩展——》管理扩展 里面下载installer Projects,

就是这搜索列表里面的第一个。
如果不能安装,自己就去网上找一下来安装。
首先这个installer好像版本有些老了,所以只支持.net Framework 4…6.1。所以请把你本身的代码框架修改成net Framework 4…6.1。如果你一开始使用的其他框架,可以右键项目,点击属性,弹出下面这个对话框。

在这个目标框架里面选择.net Framework 4.6.1 就可以了。
如果下拉菜单里面没有这个选项的话,那你就点击下拉菜单里的安装其他框架,下载一个就可以了。还有就是安装的时候要选择 developer pack 版本,安装,否则没用。

注意如果没有修改框架为.net Framework 4.6.1版本,它会提示要你安装,可是不论你怎么安装,安装什么版本都没有,只能修改目标框架,这都是血的教训啊!

还有就是如果你要修改图标,可以左键你的setup project,在左下角里面有个这种菜单栏

其中的AddRemoveProgramIcon就是设置图标的。
不过还有一点要注意,你如果直接在网上下载,或者是自己修改后缀名的图片是没有办法使用的。
你需要先在网上下载相应的icon文件,然后先设置下方对话框中的图标,然后才能去设置AddRemoveProgramIcon中的icon文件。
并且还要注意 将这个icon文件写入到application Folder,只有这样才能安装到别人电脑上也能使用。

还有就是设置这个安装文件的默认安装位置。
你需要做的就是左键点击 你的setup project文件——》view——》文件系统

出现这样一个界面
左键点击第一个文件夹 application Folder,然后找到右下角属性面板

在DefaultLocation里面设置你想要设置的文件夹路径。
————————————————
版权声明:本文为CSDN博主「永远的小白虾」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41487299/article/details/98482421

winform 项目获取app.config 中appSettings节点数据 - 承影剑 - 博客园

mikel阅读(1204)

来源: winform 项目获取app.config 中appSettings节点数据 – 承影剑 – 博客园

< ?xml version="1.0" encoding="utf-8" ?>






















http://192.168.1.155:8013/DataService/WebService/Interface/UpgradeFile.asmx




然后在winform中cs文件里这样调用:

///

/// 获取配置文件里appsettings的数据
///

/// ///
public string GetAppsettingStr(string str)
{
AppSettingsReader appReader = new AppSettingsReader();
return appReader.GetValue(str, typeof(string)).ToString();
}

SQL Server未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序 - 踏雪有迹的博客 - CSDN博客

mikel阅读(5428)

来源: SQL Server未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序 – 踏雪有迹的博客 – CSDN博客

转载自其他博主,仅技术交流,如有冒犯侵删
本人实测SQL Server2017,win10下office2016解决该问题,下载了2007 Office System后可以正常使用SQL数据导入。
因某些问题请点击阅读更多,可见文章内容

其实,这种错误的可能性有几种,比如:

1.没有安装数据访问组件,需要安装相应版本的数据访问组件;

2.没有安装相应版本的Office客户端,需要安装相应版本的Office客户端;

3.Microsoft.Jet.OLEDB.4.0在64位系统上不支持,需要修改架构,从x64改为x86,无论是WinForm还是ASP.NET;或者修改连接字符串为Microsoft.ACE.OLEDB.12.0并且安装AccessDatabaseEngine x64数据访问组件;

4.没有在IIS应用程序池配置默认属性,需要在相应的IIS应用程序池启用32位应用程序;

下面是我收集整理的一些解决方案。

 

 

【错误】:未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序。

说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.InvalidOperationException: 未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序。

下载Microsoft 2007 Office System 驱动程序:数据连接组件安装

http://download.microsoft.com/download/7/0/3/703ffbcb-dc0c-4e19-b0da-1463960fdcdb/AccessDatabaseEngine.exe

概述

此下载将安装一组组件,非 Microsoft Office 应用程序可以使用它们从 2007 Office system 文件中读取数据,例如从 Microsoft Office Access 2007(mdb 和 accdb)文件以及 Microsoft Office Excel 2007(xls、xlsx 和 xlsb)文件中读取数据。这些组件还支持与 Microsoft Windows SharePoint Services 和文本文件建立连接。
此外,还会安装 ODBC 和 OLEDB 驱动程序,供应用程序开发人员在开发与 Office 文件格式连接的应用程序时使用。

系统要求

支持的操作系统: Windows Server 2003 Service Pack 1, Windows Vista, Windows XP Service Pack 2

    • 此下载适用于以下 Office 程序:
      • 2007 Microsoft Office system
使用此下载:

  1. 如果您是应用程序用户,请查阅应用程序文档以获得有关如何使用相应的驱动程序的详细信息。
  2. 如果您是使用 OLEDB 的应用程序开发人员,请将 ConnectionString 属性的 Provider 参数设置为“Microsoft.ACE.OLEDB.12.0”如果您是使用 ODBC 连接到 Microsoft Office Access 数据的应用程序开发人员,请将连接字符串设置为“Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=path to mdb/accdb file”
    • 如果要连接到 Microsoft Office Excel 数据,请将“Excel 12.0”添加到 OLEDB 连接字符串的扩展属性中。
  3. 如果您是使用 ODBC 连接到 Microsoft Office Excel 数据的应用程序开发人员,请将连接字符串设置为“Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=path to xls/xlsx/xlsm/xlsb file”

详情与下载:

Microsoft Access Database Engine 2007 Office system 驱动程序:数据连接组件
Microsoft Access Database Engine 2010 Redistributable

 

 
【错误】:访问Excel 2007 出错,未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序。
 
场景描述:windows 2008 r2 x64版本的操作系统中通过oledb提供程序连接访问Excel2007/2003时,程序会报如下错误:

System.InvalidOperationException: The ‘Microsoft.ACE.OLEDB.12.0’ provider is not registered on the local machine.

此查找资料认为产生此种错误的原因有两种:

1、在Windows2008r2 x64 OS,在没有装Office2007客户端时,或没有安装“数据连接组件”

2、当前Web应用程序的应用程序池是64位的Sharepoint应用程序池下时,因为提供连接Excelprovider不支持当前64版本的操作系统

解决方案:

方案1:

安装MS的数据连接组件AccessDatabaseEngine(或安装office 2007客户端),并将当前承载通过oledb提供程序去访问Excel2007Web application对应的应用程序池“启用兼容32位应用程序”,

在对应的 IIS 应用程序池中,“设置应用程序池默认属性”右击/“高级设置”/”启用32位应用程序,设置为 true

方案2:

安装AccessDatabaseEngine_64版并且要安装64位版的office 2010客户端

方案3:

若目标应用程序不能将应用程序池启用兼容32位应用程序,只能在64位应用程序池下运行,且又想有上传Excel的功能,可按如下方式:

a、创建ASP.NET WebService application 程序,并通过WebService来连接访问Excel

b、将此webservice application的应用程序池按方案1方式设置“启用兼容32位应用程序”。

c、在目标应用程序中添加此webservice

 

本文来自cnblogs:http://www.cnblogs.com/q149072205/archive/2012/03/29/2423323.html