RSS阅读器

5◎1期间,呆的实在无聊了,就突然写做点事情,非常强烈的想做一个rss阅读器玩。


用了3~4天的业余时间,写了一个rss阅读器。

其实功能都很简单的,网上类似的工具也挺多的。虽然我做这个还有点bug。

但是自己能够做出自己喜欢用的东西,那种感觉不是一般人能够体验到的。

“自己写代码总是可以丰衣足食。特别庆幸自己是技术出身,在互联网的世界里,或许商务很重要,或许资金很重要,但只有深切了解技术的人才能享受编点程序比吃个苹果还开心的那种心情.

互联网归根到底,首先是技术的革命才带来了信息革命,才有了商业的革命。”
————引自王建硕的博客

Product : Rss 阅读器
系统需求: Windows2000/XP/2003
其它需求: .Net Framework 2.0

 

C# 2.0 实现简单的ORM工具

背景

06年8月份在公司用java实现了一套简单的orm工具,主要是针对jdk5.0提供的annotation特性,通过反射来实现对数据库操作的装箱、拆箱操作。

本来想放到blog上和大家共同share一下经验,后来测试jdk6.0的jdbc4.0特性时候发现jdbc4.0已经提供了类似类似orm的类库,只要db厂商实现某些接口,该厂商的bd-J-Driver就可以支持该特性了。目前主流的厂商还没有提供对jdbc4.0的支持,但是迟早要支持的,所以没有写这个部分。

后来改写成c#版本,和大家share一下。

可以把每个model类看作对应一个或者多个结构相同的表,因为有些应用我们要做分表操作。以下例子中以一个model类对应一个表为主。

核心思想是对类,以及对应的属性做上对应的标记,然后特定的工具通过对当前类的实例反射得到类上的标记,然后实现对数据库的相关操作。

c#里面提供了Attribue如果你对此不是很熟悉,请先看看相关资料有助于你对以下代码的理解。

我们先提供一个只对类起作用的Attribue,代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace Moqee.Db.Annotations
{
 
    /// <summary>
    /// 对类定义的属性
    /// 
    /// </summary>
 
    [AttributeUsage(AttributeTargets.Class,AllowMultiple=false,Inherited=false)]
    public class BeanAttribute:Attribute
    {
        //设置表名
        private string tabname = "";
 
        public string Tabname
        {
            get { return tabname; }
            set { tabname = value; }
        }
        //该类的所有字段是否自动映射
        private bool afm = true;
 
        public bool Afm
        {
            get { return afm; }
            set { afm = value; }
        }
 
        public BeanAttribute() { }
 
    }
}

BeanAttribute代码结束。
接下来实现一个对属性起作用的Attribute.

using System;
using System.Collections.Generic;
using System.Text;
 
namespace Moqee.Db.Annotations
{
    /// <summary>
    /// 定义一个对类public属性描述的注解类
    /// </summary>
 
    [AttributeUsage(AttributeTargets.Property,AllowMultiple=true,Inherited=false)]
    public class PropertyAttribute:Attribute
    {
        /// <summary>
        /// 数据库表字段名称
        /// </summary>
        private string fieldName = "";
 
        public string FieldName
        {
            get { return fieldName; }
            set { fieldName = value; }
        }
       /// <summary>
       /// 对应的c#类型
       /// </summary>
        private Type fieldCSType = typeof(string);
 
        public Type FieldCSType
        {
            get { return fieldCSType; }
            set { fieldCSType = value; }
        }
        /// <summary>
        /// 是否是主键
        /// </summary>
        private bool isPrimary = false;
 
        public bool IsPrimary
        {
            get { return isPrimary; }
            set { isPrimary = value; }
        }
        /// <summary>
        /// 该方法是否映射
        /// </summary>
        private bool isMapping = true;
 
        public bool IsMapping
        {
            get { return isMapping; }
            set { isMapping = value; }
        }
 
        private System.Data.DbType fieldDbType;
 
        public System.Data.DbType FieldDbType
        {
            get { return fieldDbType; }
            set { fieldDbType = value; }
        }
 
    }
}

代码完毕。

下面有一个测试model类。

using System;
using System.Collections.Generic;
using System.Text;
using Moqee.Db.Annotations;
using Moqee.Common;
 
namespace Moqee.Book.Business
{
    [Bean(Tabname="T_CATALOG",Afm=true)]
   public class Catalog
    {
 
       private long guid;
       private int status = BookConstants.OPEN_STATUS;
       private int priority = 0;
        [Property(FieldName="priority",FieldCSType=typeof(Int32))]
       public int Priority
       {
           get { return priority; }
           set { priority = value; }
       }
        [Property(FieldName="status",FieldCSType=typeof(Int32))]
       public int Status
       {
           get { return status; }
           set { status = value; }
       }
        [Property(FieldCSType=typeof(Int64),FieldName="guid",IsPrimary=true)]
        public long Id
        {
            get { return guid; }
            set { guid = value; }
        }
        private string name;
        [Property(FieldName="name",FieldCSType=typeof(string))]
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }
}

下面看如何解析这个类以得到里面的数据类型

private void ParserClassTag(Type type)
        {
            object[] atts = type.GetCustomAttributes(typeof(BeanAttribute), false);
            if (atts == null||atts.Length==0) return null;
            BeanAttribute pa = (BeanAttribute)atts[0];
 
            PropertyInfo[] props = type.GetProperties();
            if (props == null) return null;
 
            //此处可以得到props里面的所有属性
            foreach (PropertyInfo pi in props)
            {
                atts = pi.GetCustomAttributes(typeof(PropertyAttribute), false);
                if (atts == null || atts.Length == 0) continue;
                PropertyAttribute patt = (PropertyAttribute)atts[0];
                ///此处可以得到里面的所有属性,
            }
 
        }

经过上面的方法,就可以得到所定义的说有属性值,可以得到表名,字段信息,insert,update等语句都可以预先得到。

如果你的应用是mysql,并且主键是自增类型,完全可以定义bean里面的主键小于0为insert否则为update。

可以定义一个 DAO接口实现一些方法。

void save(object obj) throws Exception;
void delete(object obj) throws Exception;
void find(object obj) throws Exception;
List<E> query(object obj) throws Exception;

…….等等方法。

可以定义一个cache工具来实现对对类属性的缓存,不用每次都动态解析属性。

java版本的思路和上面非常类似,有兴趣你可以自己实现一下。

.Net平台实战Mail C#版本

完全按照RFC821/822协议,用Socket实现SendMail模型。

对于mail服务来说,发送相对解析来说是很简单的。本文主要是用Socket来实现SendMail服务。

程序名称SendMail.cs
辅助工具Base64.cs

调用方法:

............
SendMail mail = new SendMail("smtp.163.com",25);
mail.Authorization=true;
mail.Username="";
mail.Password="";
mail.HtmlStyle=true;
mail.From="my-mail";
mail.To=new string[]{"mail1","mail2"};
 
if(mail.connect())
{
 
bool b=mail.send("标题","内容");
MessageBox.Show(b?"信已经成功提交到对方服务器":"发送信件失败");
 
}else{
MessageBox.Show("连接不上SMTP服务器");
}
..........

其中SendMail中的成员属性.
对于附件来说,所有的类定都定义为:application/octet-stream也就是下载。但是我测试发现gmail会把图片自动显示出来

系统截图:

该工程已经提交到 Google Code:

http://code.google.com/p/rfc821/