[我有废话要说]
PA的U。M界面的树也是我封装的,做这个功能的时候,我希望它可以像smart-gwt的treeGrid一样好用。
不过我不会C#,也第一次写ASP控件,还想让他像treeGrid……在这个难度上,我想再加点,把我的树写的通用又好维护,于是我决定好好设计,加入设计模式的思想:)
[正文——封个控件来画树]
需求:
领导说写个读取XML配置,让后封装成树,在界面上展示出来。
我是个画蛇添足的程序员,我想分两步完成,希望这个题目能两天就写完。
第一步:
从XML解析一棵树,放到tree中。并且考虑:如果XML格式变了、如果不从XML取数据库……要让我的代码尽量满足开闭原则。
第二步:
做一个渲染树的控件,将这个树丢到控件中,树就画出来了,可以多列。
开始干活:
我的树的设计

用户通过工厂类得到一个XML工厂。
XMLTreeReader工厂解析XML文件,把XML配置的指定解析自己的ITreeReader返回。(比如扁平或层级的表示树形的XML文件)
ITreeReader一拿到就可以开始干活了,ITreeReader解析xml的节点,把数据封装到树结构ITreeNode中。
这里需要注意的是:ITreeNode表示一个树的树根节点,有节点的属性,还有子节点。因此ITreeReader解析时候,需要创建子节点,也就是ITreeNode对象。而ITreeNode是接口,不能new出来,所以ITreeReader需要知道ITreeNode的实现类,于是我传入ITreeReader一个ITreeNode的实现类,反射来创建对象。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public interface ITreeReaderFactory
{
ITreeReader createTreeReader();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public class XMLTreeRreaderFactory:ITreeReaderFactory
{
private string xmlPath {set;get; }
public XMLTreeRreaderFactory(string path)
{
xmlPath = path;
}
public ITreeReader createTreeReader()
{
//解析xmlPath路径下的xml文件,根据XML配置取得解析该XML对应的类,反射回去.
//这里把解析XML的一段省略了先,直接写死读到了xml配置的类:
string className = "com.Origin.Base.test.mywork.Tree.SimpleTreeReader";
Type type = Type.GetType(className);
Console.WriteLine(" 解析XML的类:" + type);
ITreeReader reader = (ITreeReader)type.Assembly.CreateInstance(className);
return reader;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public interface ITreeReader
{
ITreeNode createTree();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public class SimpleTreeReader:ITreeReader
{
private static string DEFAULT_NODE_CLASS = "com.Origin.Base.test.mywork.Tree.MyTreeNode";
private string treeNodeClassName { set; get; }
public ITreeNode createTree()
{
ITreeNode treeNode = createNode();
//根据XML的结构,解析XML文件,封装到ITreeNode的对象中,返回
//这里不读取XML了,直接用假数据封装下。
treeNode.putAttribute("name"," 用户管理");
treeNode.putAttribute("url"," /userManage.html");
//创建子树
ITreeNode subNode = createNode();
subNode.putAttribute("name", "创建用户");
subNode.putAttribute("url", " /createUser.html");
treeNode.addSubNode(subNode);
return treeNode;
}
private ITreeNode createNode()
{
if (treeNodeClassName == null)
{
treeNodeClassName = DEFAULT_NODE_CLASS;
}
//再次用到反射
Type type = Type.GetType(treeNodeClassName);
ITreeNode treeNode = (ITreeNode)type.Assembly.CreateInstance(treeNodeClassName);
return treeNode;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace com.Origin.Base.test.mywork.Tree
{
public abstract class ITreeNode
{
protected IList<ITreeNode> subNodes { get; set; }
//设置当前节点的key-value对
public abstract void putAttribute(object key, object value);
//根据key得到对应的值
public abstract object getAttribute(object key);
//为当前节增加一个子节点,在它的节点的下一级节点的末尾增加
public abstract void addSubNode(ITreeNode node);
public abstract IList<ITreeNode> getSubNodes();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
namespace com.Origin.Base.test.mywork.Tree
{
public class MyTreeNode : ITreeNode
{
private Hashtable attributes = new Hashtable();
//设置当前节点的key-value对
public override void putAttribute(object key, object value)
{
attributes.Add(key,value);
}
//根据key得到对应的值
public override object getAttribute(object key)
{
if (attributes.Contains(key))
{
return attributes[key];
}
else
{
return null;
}
}
//为当前节增加一个子节点,在它的节点的下一级节点的末尾增加
public override void addSubNode(ITreeNode node)
{
if (subNodes == null)
{
subNodes = new List<ITreeNode>();
}
subNodes.Add(node);
}
public override IList<ITreeNode> getSubNodes()
{
return subNodes;
}
}
}
看看client调用:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using com.Origin.Base.test.mywork.Tree;
namespace ConsoleApplication1
{
class Program
{
private ITreeReaderFactory factory = new XMLTreeRreaderFactory(@"D:\\menu.xml");
public ITreeNode fetchTreeNode()
{
ITreeNode root = null;
ITreeReader reader = factory.createTreeReader();
root = reader.createTree();
return root;
}
static void Main(string[] args)
{
Console.WriteLine("start...");
Program p = new Program();
ITreeNode root = p.fetchTreeNode();
string tab ="";
printTree(root, tab);
Console.ReadLine();
}
public static void printTree(ITreeNode node,string s)
{
s = " " + s;
Console.WriteLine(s + "NAME = " + node.getAttribute("name") + " url = " + node.getAttribute("url"));
IList<ITreeNode> subNodes = node.getSubNodes();
if (subNodes == null)
{
return;
}
for (int i = 0; i < subNodes.Count; i++)
{
printTree(subNodes[i],s);
}
}
}
}
输出:


本文介绍了一种使用C#和设计模式思想封装XML配置树的方法。通过构建灵活且可维护的树形结构,实现了从XML文件中读取配置并将其转化为树形结构的功能。
498

被折叠的 条评论
为什么被折叠?



