好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

如何将List<T>转换相应的Html(xsl动态转换)(一)

如何将List<T>转换相应的Html(xsl动态转换)(一)

一、前言

根据指定的xsl样式将List<T>转换相应的Html,其中涉及到怎样将List<T>转换成DataTable,如何将xml文本、xsl样式文本动态转换成html以及如何设置以及控制xsl样式。主要步骤如下:

步骤一、 将List<T>转换成DataTable 。

步骤二、 将Xml与Xsl动态转换成Html 。

步骤三、设置以及控制Xsl的内容样式。

以上的三个步骤本人将以此顺序介绍相关的内容,分别对应相关的随笔,因为本人上班的时候不能上网以及时间上的问题,所以才将该文章分3次来写。

二、类图设计

以上的内容涉及的类图虽然很简单,但是本人还是花了不少时间的来实现具体功能,代码质量还是可以保证的。EntityMapper负责将List<T>转换成DataTable(目前先将就着用这个,还有一个比较复杂的,涉及的东西比较多,此处不会讲解,以后有时间再写),XslTransform负责将xml文本、xsl文本转换成html,XslTransformFacade外观模式封装其中的细节,如下:

 

三、将List<T>转换成DataTable,再转换成xml的具体实现

这里主要是个思路的问题,先将List<T>转换成DataTable,然后将DataTable添加到DataSet中,最后通过DataSet的GetXml()方法获取Xml内容。这里思路正确的话,实现不是很复杂。先看下XslTransformFacade类,基本思路都封装在该类中:

 1       public   class  XslTransformFacade
 2       {
 3            public   static   string  ToHtml < T > (List < T >  entities, string  xslText)  where  T :  new ()
 4           {
 5                if  (ValidateArgs(entities,xslText))
 6               {
 7                    return   string .Empty;
 8               }
 9  
10                string  xmlText =  GetXmlText < T > (entities);
11  
12                using  (XslTransform xslTransform  =   new  XslTransform())
13               {
14                    return  xslTransform.Transfer(xmlText, xslText);
15               }
16           }
17  
18            private   static   bool  ValidateArgs < T > (List < T >  entities,  string  xslText)
19           {
20                return  entities  ==   null   ||  entities.Count  ==   0  
21                    ||   string .IsNullOrWhiteSpace(xslText);
22           }
23  
24            private   static   string  GetXmlText < T > (List < T >  entities)  where  T :  new ()
25           {
26                using  (DataSet dataSet  =   new  DataSet( " DataSet " ))
27               {
28                   DataTable dataTable  =  EntityMapper.ToDataTable < T > (entities);
29                   dataSet.Tables.Add(dataTable);
30                    return  dataSet.GetXml();
31               }
32           }
33       }

这一步骤主要是通过GetXmlText < T > (List < T >  entities) 方法来实现的。EntityMapper.ToDataTable < T > (entities)方法将在下面介绍。生成的Xml如下(示例):

- < DataSet >
-   < MapperInfo >
   < Name > MapperInfoIndex0 </ Name >  
   < CreatedTime > 2011 - 05 - 24T00: 27 : 23.734375 + 08 : 00 </ CreatedTime >  
   < IsActive > true </ IsActive >  
   < Value > 0 </ Value >  
   < Percent > 0 </ Percent >  
   < TargetUrl > www.codeplex.com ? Id = 0 </ TargetUrl >  
   </ MapperInfo >
-   < MapperInfo >
   < Name > MapperInfoIndex1 </ Name >  
   < CreatedTime > 2011 - 05 - 24T00: 27 : 23.734375 + 08 : 00 </ CreatedTime >  
   < IsActive > false </ IsActive >  
   < Value > 1 </ Value >  
   < TargetUrl > www.codeplex.com ? Id = 1 </ TargetUrl >  
   </ MapperInfo >
- </ DataSet >

其次第12-15行主要是将xmlText、xslText转换成html,这将在后续的文章中介绍具体实现:

12                using  (XslTransform xslTransform  =   new  XslTransform())
13               {
14                    return  xslTransform.Transfer(xmlText, xslText);
15               }

四、将List<T>转换成DataTable

这里主要是通过反射将List<T>转换成DataTable。其中需要设置DataTable的DataColumnCollection集合以及设置DataRowCollection集合。具体代码如下:

 1        public   sealed   class  EntityMapper 
 2       {
 3            public   static  DataTable ToDataTable < T > (List < T >  entities)  where  T :  new ()
 4           {
 5                if  (entities  ==   null   ||  entities.Count  ==   0 )
 6               {
 7                    return   new  DataTable();
 8               }
 9  
10                using  (DataTable dataTable  =   new  DataTable( typeof (T).Name))
11               {
12                   PropertyInfo[] properties  =   typeof (T).GetProperties();
13  
14                   SetColumnsType(properties, dataTable);
15                   SetTableContent < T > (entities, properties, dataTable);
16  
17                    return  dataTable;
18               }
19           }
20  
21            private   static   void  SetTableContent < T > (List < T >  entities, 
22               PropertyInfo[] properties, DataTable dataTable)
23           {
24                foreach  (T entity  in  entities)
25               {
26                   AddTableRowsAndContent < T > (properties, entity,dataTable);
27               }
28           }
29  
30            private   static   void  AddTableRowsAndContent < T > (PropertyInfo[] properties,
31               T entity, DataTable dataTable)
32           {
33               DataRow newRow  =  dataTable.NewRow();
34                foreach  (PropertyInfo propertyInfo  in  properties)
35               {
36                    if  ( ! CanGetPropertyValue(propertyInfo,dataTable))
37                   {
38                        continue ;
39                   }
40  
41                    try
42                   {
43                        object  objValue  =  propertyInfo.GetValue(entity,  null );
44                       newRow[propertyInfo.Name]  =  objValue  ??  DBNull.Value;
45                   }
46                    finally  
47                   {
48                   }
49               }
50  
51               dataTable.Rows.Add(newRow);
52           }
53  
54            private   static   bool  CanGetPropertyValue(PropertyInfo propertyInfo, DataTable dataTable)
55           {
56                return  propertyInfo.CanRead  &&  
57                   dataTable.Columns.Contains(propertyInfo.Name);
58           }
59  
60            private   static   void  SetColumnsType(PropertyInfo[] properties, DataTable dataTable)
61           {
62               Type colType  =   null ;
63  
64                foreach  (PropertyInfo propInfo  in  properties)
65               {
66                    if  (propInfo.PropertyType.IsGenericType)
67                   {
68                       colType  =  Nullable.GetUnderlyingType(propInfo.PropertyType);
69                   }
70                    else
71                   {
72                       colType  =  propInfo.PropertyType;
73                   }
74  
75                    if  (colType.FullName.StartsWith( " System " ))
76                   {
77                       dataTable.Columns.Add(propInfo.Name, colType);
78                   }
79               }
80           }
81        }

这里主要的操作步骤为以下2行代码:

14                   SetColumnsType(properties, dataTable);
15                   SetTableContent < T > (entities, properties, dataTable);

14行设置列的类型,15行设置DataRowCollection的DataRow内容,对于上面的代码,再多的解释都是无用的,看具体代码就行了。

 

其中需要解释一下的就是54-58行:

54            private   static   bool  CanGetPropertyValue(PropertyInfo propertyInfo, DataTable dataTable)
55           {
56                return  propertyInfo.CanRead  &&  
57                   dataTable.Columns.Contains(propertyInfo.Name);
58           }
因为当属性不可读,并且DataColumnCollection不包行该属性名时,赋值可能会抛出异常的。

其次还提一下第10行:

10                using  (DataTable dataTable  =   new  DataTable( typeof (T).Name))

这里用using来释放资源,主要是使代码中不存在任何警告,警告有时候使系统奔溃也有可能。否则进行代码分析的时候会出现警告信息,如下图所示:

 

五、DataTable 转换成List<T>  (这个是附加的,与此主题无关,但是也是EntityMapper 的一部分)

虽然以前写了一篇《  将DataRow转换成相应的对象(通用以及泛型操作)  》 ,但是并不是将DataTable 转换成List<T>,后续也有些地方进行了改进,代码如下:

public   static  List < T >  ToEntities < T > (DataTable dataTable)  where  T :  new ()
        {
            List < T >  entities  =   new  List < T > ();
             if  (dataTable  ==   null   ||  dataTable.Rows  ==   null
                 ||  dataTable.Rows.Count  ==   0 )
            {
                 return  entities;
            }

             foreach  (DataRow dataRow  in  dataTable.Rows)
            {
                entities.Add(ToEntity < T > (dataRow));
            }

             return  entities;
        }

         public   static  T ToEntity < T > (DataRow dataRow)  where  T :  new ()
        {
             if  (dataRow  ==   null )
            {
                 return   default (T);
            }

            T item  =  Activator.CreateInstance < T > ();
            CopyToEntity(item, dataRow);

             return  item;
        }

         public   static   void  CopyToEntity( object  entity, DataRow dataRow)
        {
             if  (entity  ==   null   ||  dataRow  ==   null )
            {
                 return ;
            }
            PropertyInfo[] propertyInfos  =  entity.GetType().GetProperties();

             foreach  (PropertyInfo propertyInfo  in  propertyInfos)
            {
                 if  ( ! CanSetPropertyValue(propertyInfo, dataRow))
                {
                     continue ;
                }

                 try
                {
                     if  (dataRow[propertyInfo.Name]  is  DBNull)
                    {
                        propertyInfo.SetValue(entity,  null ,  null );
                         continue ;
                    }
                    SetPropertyValue(entity, dataRow, propertyInfo);
                }
                 finally
                {
                }
            }
        }

         private   static   bool  CanSetPropertyValue(PropertyInfo propertyInfo,
            DataRow dataRow)
        {
             return  propertyInfo.CanWrite  &&  
                dataRow.Table.Columns.Contains(propertyInfo.Name); 
        }

         private   static   void  SetPropertyValue( object  entity,
            DataRow dataRow, PropertyInfo propertyInfo)
        {
             if  (propertyInfo.PropertyType  ==   typeof (DateTime ? )  ||
                propertyInfo.PropertyType  ==   typeof (DateTime))
            {
                DateTime date  =  DateTime.MaxValue;
                DateTime.TryParse(dataRow[propertyInfo.Name].ToString(),
                    CultureInfo.CurrentCulture, DateTimeStyles.None,  out  date);

                propertyInfo.SetValue(entity, date,  null );
            }
             else
            {
                propertyInfo.SetValue(entity, dataRow[propertyInfo.Name],  null );
            }
        }

六、EntityMapper.ToDataTable<T>(List<T> entities)方法的单元测试

ToDataTable<T>(List<T> entities)方法的具体单元测试如下,仅仅是主要功能的测试:

public   class  EntityMapperTest
 2       {
 3           [TestMethod()]
 4            public   void  ToDataTableTest()
 5           {
 6               List < MapperInfo >  entities  =  CreateMapperInfos( 9 );
 7               DataTable result  =  EntityMapper.ToDataTable < MapperInfo > (entities);
 8               Assert.IsNotNull(result);
 9               Assert.IsNotNull(result.Rows);
10               Assert.AreEqual( 9 , result.Rows.Count);
11                int  index  =   0 ;
12                foreach  (DataRow dataRow  in  result.Rows)
13               {
14                   Assert.AreEqual(dataRow[ " Name " ], 
15                        string .Concat( " MapperInfoIndex " , index.ToString()));
16                   Assert.AreEqual(dataRow[ " IsActive " ], index  %   2   ==   0   ?   true  :  false );
17                   Assert.AreEqual(dataRow[ " Value " ], index);
18                   Assert.IsNotNull(dataRow[ " CreatedTime " ]);
19                   Assert.AreEqual(dataRow[ " Percent " ], DBNull.Value);
20                   index ++ ;
21                   
22               }
23           }
24  
25            private  List < MapperInfo >  CreateMapperInfos( int  count)
26           {
27               List < MapperInfo >  entities  =   new  List < MapperInfo > ();
28                for  ( int  index  =   0 ; index  <  count; index ++ )
29               {
30                   entities.Add( new  MapperInfo()
31                   {
32                       Name  =   string .Concat( " MapperInfoIndex " , index.ToString()),
33                       IsActive  =  (index  %   2   ==   0   ?   true  :  false ),
34                       CreatedTime  =  DateTime.Now,
35                       Value  =  index
36                   });
37               }
38  
39                return  entities;
40           }
41       }

七、总结

最近二个多月,忙死我了。这段时间转SIT测试了,终于又可以轻松一阵了,哈哈。这些随笔的内容都是上班时间之外写的,每次写的代码都做单元测试,主要是避免出现显而易见的BUG,以及将代码积累并且更新到自己的框架中。接下来的一篇主要是如何将xml文本、xsl文本动态转换成html,这个花费了本人一段时间,一直在摸索才整理出来的,主要是通过XslCompiledTransform.Transform(XmlReader input, XmlWriter results)来实现的,本人已经更新了几个版本了,这个应该是最终版本的,同时也是最精简的版本。

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于如何将List<T>转换相应的Html(xsl动态转换)(一)的详细内容...

  阅读:48次