跟小D每日学口语

SilverLight OOB模式将实体转换成XML文件写入本地文件

先闲话一番,因为最近接到的一个项目,有一个要求是在完全断网的情况下不影响软件使用,且交易数据不会丢失。需要基于云平台做开发,且别人的平台只支持.net Framework4.0((~ o ~)~zZ)。最终决定采用SilverLight来做这个项目,又是无尽的学啊……

起因:交易数据(都是实体)需要以XML的形式存储在本地,断网时能够正常操作软件。

难点:1:Silverlight 4 API仅支持存取“我的文档”,“我的音乐”,“我的图片”和“我的视频”目录以及“Program Files”和“Cookies”目录

    2:将实体对象换成XML文件

思考:是否可以通过非SL类来实现本地操作;实体转XML通过反射实现

带着问题开始无限的coding了……

 

先建立实体类(Order对象)

public class Order    {
        private int id;
        [ColumnAttribute("UserID")]
        public int UserID
        {
            get { return id; }
            set { id = value; }
        }

        private string userName;
        [ColumnAttribute("UserName")]
        public string UserName
        {
            get { return userName; }
            set { userName = value; }
        }

        string age;
        public string UserAge
        {
            get { return age; }
            set { age = value; }
        }

}

还需要实现一个特性(这个是为了操作只需要的数据准备的,当然这个项目中用到特性的地方只对要写入XML的实体进行筛选,因为不是所有实体属性都要写入xml文件)

[AttributeUsage(AttributeTargets.Property)]
    public class ColumnAttribute : Attribute
    {
        public ColumnAttribute(string property) { this.Property = property; }

        public string Property { get; set; }
    }

 

然后开始写实体生成XML文件的方法了(不想新建类,我就在Order下新建了一个Update方法)

public string Update(User user)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(@"<?xml version=""1.0"" encoding=""utf-8""?>");
            sb.AppendLine(@"<ArrayOfOrder>");
            sb.AppendLine(@"    <Order>");
            PropertyInfo[] pro_base = user.GetType().GetProperties();

            for (int i = 0; i < pro_base.Length; i++)
            {
                object[] obj = pro_base[i].GetCustomAttributes(typeof(ColumnAttribute), false);//获取用户自定义的特性
                if (null != obj && obj.Length != 0) //这里用特性进行筛选哪些实体属性不需要
                {
                    string startElement = string.Format("       <{0}>", (obj.GetValue(0) as ColumnAttribute).Property);//XML元素的起始标签
                    string stringElement = pro_base[i].GetValue(user, null).ToString().Trim();//XML元素的标签值

                    string endElement = string.Format(@"</{0}>", pro_base[i].Name);//XML元素的结束标签
                    sb.AppendLine(startElement + stringElement + endElement);
                }

            }
            sb.AppendLine(@"    </Order>");
            sb.AppendLine(@"</ArrayOfOrder>");
            return sb.ToString();

        }

 

然后我在MainPage.xaml中添加了一个按钮(转换)和按钮(写入本地)和一个文本框(显示Order对象调用Update的返回结果)

在按钮的Click事件中加了下面的代码(仅仅是查看实体类转换成XML的方法)

private void button3_Click(object sender, RoutedEventArgs e)
        {
            Order o = new Order{ UserID = 1, UserName = "Roy" };//实例化Order对象并赋初始值
            this.txtShow.Text = o.Update(o);
        }

最后txtShow的文本框显示的结果如下:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfOrder>
    <Order>
       <UserID>1</UserID>
       <UserName>Roy</UserName>
    </Order>
</ArrayOfOrder>

 

最后面我们就只要想办法保存到本地了,上篇文章说到COM组件对本地文件的读取(http://www.cnblogs.com/aijie/archive/2011/09/22/2185453.html),这里就只附上存入的代码,如下:

点击写入本地按钮,后置代码中自动生成按钮的Click事件,在事件中添加代码

using (dynamic dym = AutomationFactory.CreateObject("Scripting.FileSystemObject"))
            {
                dynamic write = dym.CreateTextFile(@"F:/order.xml", 1, false);
                write.WriteLine(this.txtShow.Text);
                write.Close();
            }

 

本来我想用最简单的方法来实现上述实体转换xml的功能,那就是

PropertyInfo[] pro_base = order.GetType().GetProperties();

for (int i = 0; i < pro_base.Length; i++)
{
  switch(pro_base[i].Name)

    case “UserID”:

    string id = string.Format(@"<{0}>{1}</{0}>",pro_base[i].Name,order.UserID);

    break;

    ……

}

上面的写法不好在于要上传的每个实体类都要这样写,而且新增表或者新增列,上面的代码也需要更改。所以采用反射可以对方法进行封装,而且新增列只需要在实体类中新增一个属性就可以了。当然用于正式项目中上述代码还需要优化。Silverlight中通过COM组件没有直接存储XML文件的方法(我比较笨,没找到),就采用上述方法来做了。在COM组件上没找到直接可以写XMLWriter和XDocument写出的值的方法,有高招还希望不吝赐教。XMLWriter和XDocument好用可无法存储到指定目录。

posted @ 2011-09-22 19:20  艾洁  阅读(661)  评论(2编辑  收藏  举报