C#反射实现简单的插件系统

如果用过一些优秀的开源或是非开源的应用软件,就会发现这些软件的一个很大的优势就是其开放性,任何有能力的人都可以为其开发不同的插件来增强其的功能。比如著名的foobar2000,Vim和TotalCommander等等。

C#的反射可以用来实现一个简单的插件系统。思路很简单,我们创建一个解决方案,包含三个工程,一个为我们的软件MyApplication,一个为插件接口IPlugin,一个为具体的插件MyPlugin。插件系统的基本思路是我们用一个接口类库,来定义我们软件可以使用的插件必须实现的方法签名。然后我们的软件MyApplication通过引用该IPlugin dll来动态调用,而具体的实现插件MyPlugin则引用该接口来实现具体的方法。这样我们的应用程序就能在不知道具体插件的情况下调用插件了。。

结构图如下:

Myapplication

关键代码也就是通过对程序集载入。搜索到对应接口的实现类。然后调用即可。

Assembly a = Assembly.LoadFrom(AssemblyName);
                foreach (Type t in a.GetTypes())
                {
                    if (t.GetInterface(“IMyFunction”) != null)
                    {
                        try
                        {
                            IMyFunction pluginclass = Activator.CreateInstance(t) as IMyFunction;
                            pluginclass.doSomething();
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.ToString());
                        }
                    }
                }
运行结果:

QQ截图20130220200408

源码下载:PluginSystem.zip

Android开发获取Map API Key

地图应用使用com.google.android.maps这个包。通过MapView控件使用。但是之前需要申请一个用于开发的API Key,这个key会和当前的计算机用户绑定。然后通过这个key去官方申请就可以拿到一个开发用的api key了 <1>首先找到用户的debug.keystore文件,可以再”运行“里面搜debug.keystore;如:c:\users\Administrator.android\debug.keystore

<2>接下来获取MD5指纹,网上很多说的有误。貌似新版默认是出现sha1加密的。通过添加-v 参数会显示所有。

首先运行cmd,在dos界面里,输入

keytool -list -v -keystore c:\users\Bystander.android\debug.keystore
命令,然后会让你输入keystore密码,

输入:android,之后,会出现指纹认证MD5,如下:

<3>去官方生成真正的api key 访问 Sign Up for the Android Maps API 输入那串值,同意条款,确定后要求用Google帐号登录。然后会拿到一个key。ok

WPF毛玻璃效果Demo和一个问题

那天看到WPF书上讲的毛玻璃效果,就去找了下效果。。忘了例子是从哪发现得了。。先看下效果,

  但是这不是重点,作者给出的代码有一个设计时错误。。错误提示为: 无法将类型为“Microsoft.Expression.Platform.WPF.InstanceBuilders.WindowInstance”的对象强制转换为类型“System.Windows.Window”,,

  中文搜了一下。没有发现有人解决过。目测。。。然后又拿英文搜了下。几经辗转。。终于是解决了。。原文在Unable to cast XAML error。其实就是将原作者这个函数修改如下的

public static void OnIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {

        if ((bool)args.NewValue == true)
        {
            Window wnd = obj as Window;
            if (wnd != null) wnd.Loaded += new RoutedEventHandler(wnd_Loaded);
        }
    }</pre> 

  也就是验证了一下转换是否成功。

下载:修改后的RGSamples

.net显示网络连接状态图标

效果图: 介绍  越来越多的软件要通过连接互联网来执行一些业务层的业务操作,比如调用web services服务,获取数据等等。 通常你可能希望知道当前你的网络连接是不是真的连上了,当然有很多种方法可以做到,比如,你可以查看System.Net 命名空间中的NetworkInterface 的状态,但是有这以太网连接并不表示你的连接真的可以用。 本文将会展示一种方法,该方法在程序的状态栏StatusStrip 显示一个简单的图标来指示是不是真的连接到了互联网。 使用代码  最简单的我们会想到使用一个Timer来进行http-get请求来判断一个特定的网页是否可用。  当然这种方法下,我们最应该考虑的就是请求不能阻塞UI线程,因此,我将使用一个BackgroundWorker 对象来进行get请求,BackgroundWorker 对象声明了DoWork方法。该方法定义了一个事件句柄,该句柄传递一个DoWorkEventArgs 类来将事件的处理结果返回到UI线程,因此,你不必与任何的UI元素进行交互,因为它运行在一个独立的线程里。 private void InitializeComponent() { // Background Worker this._worker = new BackgroundWorker(); this._worker.WorkerReportsProgress = false; this._worker.WorkerSupportsCancellation = false; this._worker.DoWork += new DoWorkEventHandler(this.BackgroundWorker_DoWork); this._worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.BackgroundWorker_RunWorkerCompleted); // Timer this._updateTimer = new Timer(); this._updateTimer.Enabled = !this.DesignMode; // Enabled when not in design mode this._updateTimer.Tick += delegate { this.OnTick(); }; } private void OnTick() { if (this. [Read More]

Html解析工具-HtmlAgilityPack

这个工具是在暑假的时候发现的。但是最后没用这个工具。不过,这个工具可是非常强悍的。。 HtmlAgilityPack主要就是解析DOM的。常用的基础类其实不多,对解析DOM来说,就只有HtmlDocument和HtmlNode这两个常用的类,还有一个 HtmlNodeCollection集合类。我给出一个抓取我博客首页文章的例子。看代码可能更清楚一点。你可以去看看压缩包里提供的文档。 xpath如果自己写表达式比较麻烦。所以我还找到了这个HtmlAgilityPack提供了的一个xpath辅助工具-HAPExplorer。都给出了地址。 首先看我的例子,抓取我博客的首页文章: using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Diagnostics; using System.Threading.Tasks; using System.IO; using System.Data; using System.Data.SqlClient; using HtmlAgilityPack; namespace leaver { class Program { static void Main(string[] args) { HtmlWeb web = new HtmlWeb(); HtmlDocument doc = web.Load("http://leaver.me/"); HtmlNode node = doc.GetElementbyId("content"); StreamWriter sw = File.CreateText("leaver.txt"); //从根节点选中class=hfeed的节点 string cfeed = node.SelectSingleNode("/html[1]/body[1]/div[1]/div[1]/div[2]/div[1]/div[1]").OuterHtml; HtmlNode hfeed = HtmlNode.CreateNode(cfeed); foreach (HtmlNode child in hfeed.ChildNodes) { if (child.Attributes["id"] == null || child. [Read More]

WCF读书笔记(3)

WCF的四大行为

  契约行为(Contract Behavior),操作行为(Operation Behavior),服务行为(Service Behavior),终结点行为(Endpoint Behavior)。

  如果把WCF看做是消息处理,对象激活与操作执行的管道,那么我们可以通过相应的行为来改变这个管道中某个环节的工作方式。比如加个密啊。什么的。

单向模式(One-Way)

  单向模式不需要服务器执行后返回一个回复,多用于不要求服务执行后返回一个回复,并且能够容忍日志记录的失败,只有返回类型为void的才允许设置为true,同理,ref和out参数作为另一种类型的输出。也是不允许的。

WCF的三种异步操作

  1.异步信道调用:客户端可以通过代理对象进行异步调用信道。

  2.One-Way消息交换:单向的消息交换一旦抵达传输层,马上返回,从而实现异步

  3.异步服务实现:服务端在具体实现服务操作的时候。采用异步调用的方式。

序列化:

  XMLSerializer序列化对象时,必须是公有,可读可写的属性,才能序列化。

WCF的四大契约

  服务契约(Service Contract),数据契约(Data Contract),消息契约(Message Contract),错误契约(Fault Contract)

信道:

  信道是为了便利WCF中客户端和服务的通信来设置的。ServiceHost为每个断点创建一个信道侦听器,侦听器产生通信通道,代理则产生一个信道发生器,发生器产生客户端的信道,两种信道相互兼容并且能有效处理之间的信息。

  实际上,通信信道是有一个分层的信道栈组成-栈中的每一个信道都在消息处理过程中负责实施一个特定动作,信道栈包含一个传输信道,一个消息编码信道,和任意数量的消息处理信道,绑定则将决定了哪些信道留在信道栈中。当行为穿过信道栈时,消息处理方式将会有所改变。。

未能加载文件或程序集“App_Web_xxxx”

今天在用WCF写服务的时候,服务一直连不上,直接查看svc文件,发现如下错误 未能加载文件或程序集“’AppWeb*, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”,*是一个随机字符串。

解决方法中:

  在web.config里配置成这样子:

 <compilation debug=“true” batch=“false”>
  就好了。中午和下午一直在搞javascript连接WCF的demo,总算是晚上搞定了,,还是老样子,,最大的体会就是很多东西就是看着简单,写起来会有各种各样的问题,比如这次,即使照着微软的官方文档来,也会有错误。动手才是王道,不管做什么。这几天忙完了,写篇文章出来。

  最后分享一下微软官方的WCF与Ajax开发实践系列课程,我只能说WCF这东西没有哪一本书比微软官方的技术培训讲的更好了,非常建议学习。

  武汉最近下雨了,天气挺凉爽,过几天准备回家吧。。

C#中XML和二进制的序列化

看书的时候,看到的。然后感觉书上的写的不清楚,于是自己写了一下。还真的有问题。 要进行序列化和反序列化,首先要定义一个可以序列化的类,方法是在类的声明前加上特性 [Serializable] 定义了一个简单的用户类,需要注意的是私有字段是不能序列化的,只有公有字段和公有属性才可以。如下 [Serializable] //特性,可以序列化 public class UserData { public string Name; public int Age; private string sex; public string Sex { set{sex=value;} get{return sex;} } public UserData() { } public UserData(string name, int age, string sex) { Name = name; Age = age; Sex = sex; } } 注意,书上有个例子没有给出默认的构造函数,实际测试时如果没有默认构造函数,是不能执行xml序列化的。注意。 然后就导入需要的命名空间。 需要导入 using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Xml.Serialization; 分贝对应文件操作,二进制序列化和xml序列化 为了方便,我封装了四个静态函数,用于实现序列化和反序列化。 //封装二进制序列化方法 public static void BinarySerialize(UserData user) { FileStream fs = new FileStream(" [Read More]

C#WinForm实现不规则窗体

这个纯属娱乐,因为其实用的不是太多,因为非主流,非标准的界面不符合用户的体验,不符合可用性功能的某一条HE规则。 为了完成这个效果,首先需要自己动手画个你需要的界面出来,界面边缘需要是一种可以很好区别的颜色,比如纯蓝色,因为实现不规则窗体是让C#使边缘颜色透明化来实现的,所以需要唯一识别。因为我用的图是一张灰色的图,我然后圈了一个蓝色的边缘。 刚开始的图; 然后新建windows应用程序。创建windows窗体并设置窗体基本属性。 (1)将 FormBorderStyle 属性设置为 None。 (2)将窗体的 BackgroundImage 属性设置为先前创建的位图文件。不必将文件添加到项目系统中;这将在指定该文件作为背景图像时自动完成。 (3)将 TransparencyKey 属性设置为位图文件的背景色,本例中为蓝色。(此属性告诉应用程序窗体中的哪些部分需要设置为透明。 ) 上面两个步骤已经完成了不规则窗体自身显示效果的制作。 有人说在24位色以下的环境中可以显示正常,但在24位色以上时黄色背景不能消失,所以上述不能胜任24位色以上环境。但我看到了一种解决方法,那就是先将背景图片添加到资源文件,然后在窗体构造时为窗体设置背景图片:   private void Form1_Load(object sender, EventArgs e){ Bitmap bmp = Properties.Resources.form2; bmp.MakeTransparent(Color.Blue); // bmp.MakeTransparent(Color.FromArgb(2,2,2));如果rgb则是这样用 this.BackColor = Color.Blue; this.BackgroundImage = bmp; this.TransparencyKey = Color.Blue; }   实测是可以的。 然后就是为窗体添加移动、关闭、最大最小化的事件。代码直接给出 private bool isMouseDown = false; //记录鼠标是否被按下 private Point position; //记录鼠标位置 private void Form1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { int x = -e. [Read More]

FreeAnony-代理采集设置工具

这个名字确实有点不太好。。因为刚开始我想到这个工具是在今天早上看到一个别人的代理工具的时候,突然想做的,没有好好规化,结果后来代码越写越多。。不过收获很大。 先看界面,因为是简单实现一下,所以就不要吐槽界面了。。 刚开始想的思路就是先去一个经常发布代理IP的网页去采集。然后解析成一条条的信息。然后显示出来。中途遇到几个问题,一个就是在做代理验证的时候,没有用多线程,导致直接界面无响应。另一个就是DataGridView控件要实现对一个数组的绑定,需要的一个实体对象。 public IPEntity[] GetIpInfo(string url) { //获得网页源码 string content = Get_Http(url); //定位代理ip位置 int start = content.IndexOf("&lt;/strong&gt;&lt;/u&gt;&lt;/a&gt;&lt;BR&gt;"); int end = content.LastIndexOf("&lt;BR&gt;&lt;SCRIPT type=text/javascript&gt;"); //提取并去除一些冗余代码 string subContent = content.Substring(start, end - start).Substring(21); subContent = subContent.Replace("&amp;nbsp; dn28.com", ""); //通过br标签分隔代理列表为数组 string[] sArray = Regex.Split(subContent, "&lt;br&gt;", RegexOptions.IgnoreCase); IPEntity[] list = new IPEntity[sArray.Length]; int j = 0; foreach (string i in sArray) { int addrpos = i.IndexOf(":"); string ipaddress = i.Substring(0, addrpos); int portpos = i. [Read More]