经过好一段时间的努力,通讯录这个简单的项目也算是暂时告一段落了,虽然还只是在那难看的黑框框(控制台)上运行,那也得拿出来亮亮相了,不过相信经过不断的学习,不断的改进,很快就能以新面孔再次跟大家见面了。
这个通讯录项目包括两大模块,第一是实体类。第二是功能类。实体类中包括字段以及字段的属性和一个重写字符串的方法。功能类中主要包括了一些处理字段的功能,比如:信息的删除,更新,以及获取整个文档的内容。当然里面还有一些其他的类,比如枚举类,比较器类,这些都是为了对用户更友好而做出的改进,让这个通讯录能够更方便的服务于大众。一起来看看这个庞然大物吧:
第一:实体类。看代码:
[Serializable]//将实体类设置为可以序列化。 class Card { string name; public string Name { get { return name; } set { name = value; } } string phone; public string Phone { get { return phone; } set { phone = value; } } string qq; public string Qq { get { return qq; } set { qq = value; } } string email; public string Email { get { return email; } set { email = value; } } string address; public string Address { get { return address; } set { address = value; } } public override string ToString() { string s = string.Format("{0}\t{1}\t{2}\t{3}\t{4}", name, phone, qq, email, address); return s; }
第二:功能类。看代码:
class CardManager { //准备一个空集合作为这个类的全局变量(存放用户读写的字段),便于用户读写 public List<Card> cards = new List<Card>(); /// <summary> /// 给这个集合做一个构造方法,将值写入集合 /// </summary> public CardManager() { //定义一个bool类型的变量,判断目标文件是否存在 bool b = File.Exists(path); //如果目标文件不存在,就返回 if (!b) { return; } //创建一个XML文档 XmlDocument doc = new XmlDocument(); doc.Load("test.xml"); XmlNode root = doc.DocumentElement; foreach (XmlNode Node in root.ChildNodes) { Card card = new Card(); string name = Node.ChildNodes[0].InnerText; string phone = Node.ChildNodes[1].InnerText; string qq = Node.ChildNodes[2].InnerText; string email = Node.ChildNodes[3].InnerText; string address = Node.ChildNodes[4].InnerText; card.Name = name; card.Phone = phone; card.Qq = qq; card.Email = email; card.Address = address; cards.Add(card); } } /// <summary> /// 将节点中的内容返回成对象 /// </summary> /// <param name="node"></param> /// <returns></returns> private Card GetCardFromNode(XmlNode node) { Card card=new Card (); foreach (XmlNode childNode in node.ChildNodes) { string nodeName = childNode.Name; string nodeText = childNode.InnerText; CardEnum ce = (CardEnum)Enum.Parse(typeof(CardEnum), nodeName); switch (ce) { case CardEnum.Name: card.Name = nodeText; break; case CardEnum.Phone: card.Phone = nodeText; break; case CardEnum.QQ: card.Qq = nodeText; break; case CardEnum.Email: card.Email = nodeText; break; case CardEnum.Address: card.Address = nodeText; break; default: break; } } return card; } //准备好的目标路径 string path = "f:\\cards.txt"; /// <summary> /// 功能方法:添加功能 /// </summary> /// <param name="card"></param> public bool Add(Card card) { //判断要添加的字段,集合中是否存在,如果存在则返回false if (GetCardByName(card.Name) != null) { return false; } //如果不存在,则将要添加的字段附加到事先准备的集合中 cards.Add(card); //将集合写入文件,并返回true Save(); return true; } /// <summary> /// 将集合写入成文件 /// </summary> private void Save() { //创建一个写入取器对象,往文件中写入东西 StreamWriter sw = new StreamWriter(path, false); //创建一个XML文档 XmlDocument doc = new XmlDocument(); //写入文档的定义节点 XmlDeclaration declare = doc.CreateXmlDeclaration("1.0", "utf-8", null); //添加一个根节点 XmlNode root = doc.CreateElement("cards"); //将定义节点和根节点都写入XML文档中去 doc.AppendChild(declare); doc.AppendChild(root); //遍历集合,逐句写入,写完后关闭流 foreach (Card card in cards) { //创建一个子节点card XmlNode childNode = doc.CreateElement("card"); //将子节点加入到根节点中 root.AppendChild(childNode); //创建5个孙子节点(即属性字段) XmlNode grandSon1 = doc.CreateElement("name"); XmlNode grandSon2 = doc.CreateElement("phone"); XmlNode grandSon3 = doc.CreateElement("qq"); XmlNode grandSon4 = doc.CreateElement("email"); XmlNode grandSon5 = doc.CreateElement("address"); //分别将5个孙子节点加入到子节点中去 childNode.AppendChild(grandSon1); childNode.AppendChild(grandSon2); childNode.AppendChild(grandSon3); childNode.AppendChild(grandSon4); childNode.AppendChild(grandSon5); //得到孙子节点的值(内容) grandSon1.InnerText = "潘静"; grandSon2.InnerText = "18700101911"; grandSon3.InnerText = "1052828278"; grandSon4.InnerText = "10528282782qq.com"; grandSon5.InnerText = "陕西永寿"; //将所有对象保存成XML文档类型,XML文档设计为子描述功能(自己认识自己到底是姓名还是电话),更方便了用户和程序员 doc.Save("test.xml"); //XmlNode childNode = doc.CreateElement("card"); //root.AppendChild(childNode); //childNode.Value = "name"; //root.Attributes.SetNamedItem(childNode); //doc.Save("test.xml"); } sw.Flush(); sw.Close(); } /// <summary> /// 获取所有通讯录信息 /// </summary> /// <returns>通讯录集合</returns> public List<Card> GetAllCards() { return cards; } /// <summary> /// 删除某个通讯录对象 /// </summary> /// <param name="name">根据某个的名字</param> public void Delete(string name) { //定义一个索引,用来存放要删除的阻断在集合中的位置,值为-1表示不存在 int index = -1; //从集合中查找这个元素,如果找到了,就结束循环 for (int i = 0; i < cards.Count; i++) { if (cards[i].Name == name) { index = i; break; } } //如果没找到,则返回 if (index == -1) { return; } //如果找到了,就删除该字段 cards.RemoveAt(index); Save(); } public Card GetCardByName(string name) { //先获取所有的通讯录对象 int index = -1; //从集合中查找这个元素,如果找到了,就结束循环 for (int i = 0; i < cards.Count; i++) { if (cards[i].Name == name) { index = i; break; } } //如果没找到,就返回null if (index == -1) { return null; } //找到之后返回这个对象 Card card = cards[index]; return card; } /// <summary> /// 通过姓名来查找实体对象 /// </summary> /// <param name="phone"></param> /// <returns>集合</returns> public List<Card> GetCardByPhone(string phone) { //创建一个集合对象 List<Card> list = new List<Card>(); //从集合中查找这个元素 for (int i = 0; i < cards.Count; i++) { //利用电话来查询,将查到的对象加到集合中去 if (cards[i].Phone == phone) { list.Add(cards[i]); } } //返回这个集合(集合中是所有电话号码相同的人) return list; } /// <summary> /// 更新通讯录 /// </summary> /// <param name="card"></param> public void UpdateCard(Card card) { //定义一个索引来存放要更新的对象在集合中的位置 int index = -1; //遍历整个集合寻找要更新的对象,找到之后更新该对象的信息,然后结束循环 for (int i = 0; i < cards.Count; i++) { if (cards[i].Name == card.Name) { cards[i].Phone = card.Phone; cards[i].Qq = card.Qq; cards[i].Email = card.Email; cards[i].Address = card.Address; index = i; break; } } //如果index=-1表示没找到,那么返回 if (index == -1) { return; } //如果找到了将更新后的集合写入文件 Save(); } /// <summary> /// 排序功能,对集合中的元素进行排序 /// </summary> /// <param name="cards"></param> /// public List<Card> Sort(CardEnum cardEnum) { for (int i = 0; i < cards.Count - 1; i++) { for (int j = 0; j < cards.Count - i - 1; j++) { int compareResult = 0; IComparer<Card> temp = null; switch (cardEnum) { case CardEnum.Name: temp = new CardNameComparer(); break; case CardEnum.Phone: temp = new CardPhoneComparer(); break; case CardEnum.QQ: temp = new CardQqComparer(); break; case CardEnum.Email: temp = new CardEmailComparer(); break; case CardEnum.Address: temp = new CardAddressComparer(); break; default: break; }//利用冒泡排序法进行排序。将相邻的两个对象进行比较,如果前面的大,那么交换位置 compareResult = temp.Compare(cards[j], cards[j + 1]); if (compareResult > 0) { Card tempCard = cards[j]; cards[j] = cards[j + 1]; cards[j + 1] = tempCard; } } } return cards; } }
下面是为几个字段做的比较器,在这里我只写出一个,基本是类似的。看代码:
class CardNameComparer : IComparer<Card> { public int Compare(Card x, Card y) { return x.Name.CompareTo(y.Name); } }
还有一个枚举类,用来限制用户输入这个类在功能类中显得尤为重要。看代码:
enum CardEnum { Name, Phone, QQ, Email, Address }
最后就是程序的实现了,这一步仍然在main方法中进行。对功能类中的方法逐个调用就可以了,在调用的时候注意返回类型是否一致。这里不给出详细代码了。
相信很快就会有通讯录(二)了,我很期待!