風語·深蓝

Agile Methodology, HeadStorm And MindMap, they will change me.
posts - 58, comments - 331, trackbacks - 14, articles - 13
  在2.0正式版发布之前,就满天的看到关于DataTable支持序列化的新特性宣传,满以为从此以后使用DataTable就和DataSet一样方便了,结果在应用项目的时候才发现并非那么回事。
  DataTable是支持序列化了,但是微软并没有把他做的特别方便,还需要我们自己来做一些工作之后才能够在WebService里面传递DataTable,否则在引用DataTable的时候会发现DataTable变成了一个什么Proxy类型。
  首先编写类DataTableSchemaImporterExtension,代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization.Advanced;
using System.Collections;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Xml;
using System.Data;

namespace Xrinehart.Tools.WebService.SchemaImporter
{
    
class DataTableSchemaImporterExtension : SchemaImporterExtension
    
{

        
// DataTableSchemaImporterExtension is used for WebServices, it is used to recognize the schema for DataTable within wsdl

        Hashtable importedTypes 
= new Hashtable();



        
public override string ImportSchemaType(string name, string schemaNamespace, XmlSchemaObject context, XmlSchemas schemas, XmlSchemaImporter importer, CodeCompileUnit compileUnit, CodeNamespace mainNamespace, CodeGenerationOptions options, CodeDomProvider codeProvider)
        
{

            IList values 
= schemas.GetSchemas(schemaNamespace);

            
if (values.Count != 1)
            
{

                
return null;

            }


            XmlSchema schema 
= values[0as XmlSchema;

            
if (schema == null)

                
return null;

            XmlSchemaType type 
= (XmlSchemaType)schema.SchemaTypes[new XmlQualifiedName(name, schemaNamespace)];

            
return ImportSchemaType(type, context, schemas, importer, compileUnit, mainNamespace, options, codeProvider);

        }




        
public override string ImportSchemaType(XmlSchemaType type, XmlSchemaObject context, XmlSchemas schemas, XmlSchemaImporter importer, CodeCompileUnit compileUnit, CodeNamespace mainNamespace, CodeGenerationOptions options, CodeDomProvider codeProvider)
        
{

            
if (type == null)
            
{

                
return null;

            }


            
if (importedTypes[type] != null)
            
{

                mainNamespace.Imports.Add(
new CodeNamespaceImport(typeof(DataSet).Namespace));

                compileUnit.ReferencedAssemblies.Add(
"System.Data.dll");

                
return (string)importedTypes[type];

            }


            
if (!(context is XmlSchemaElement))

                
return null;



            
if (type is XmlSchemaComplexType)
            
{

                XmlSchemaComplexType ct 
= (XmlSchemaComplexType)type;

                
if (ct.Particle is XmlSchemaSequence)
                
{

                    XmlSchemaObjectCollection items 
= ((XmlSchemaSequence)ct.Particle).Items;

                    
if (items.Count == 2 && items[0is XmlSchemaAny && items[1is XmlSchemaAny)
                    
{

                        XmlSchemaAny any0 
= (XmlSchemaAny)items[0];

                        XmlSchemaAny any1 
= (XmlSchemaAny)items[1];

                        
if (any0.Namespace == XmlSchema.Namespace && any1.Namespace == "urn:schemas-microsoft-com:xml-diffgram-v1")
                        
{

                            
string typeName = typeof(DataTable).FullName;

                            importedTypes.Add(type, typeName);

                            mainNamespace.Imports.Add(
new CodeNamespaceImport(typeof(DataTable).Namespace));

                            compileUnit.ReferencedAssemblies.Add(
"System.Data.dll");

                            
return typeName;

                        }


                    }


                }


            }


            
return null;

        }


    }



}

  为此类添加进一个项目中,并将此项目进行强命名后编译。

  然后,把该Assembly程序集加入到GAC中。

  最后修改本机的machine.config,代码如下:
      <sectionGroup name="system.xml.serialization" type="System.Xml.Serialization.Configuration.SerializationSectionGroup, System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      
<section name="schemaImporterExtensions" type="System.Xml.Serialization.Configuration.SchemaImporterExtensionsSection, System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      
<section name="dateTimeSerialization" type="System.Xml.Serialization.Configuration.DateTimeSerializationSection, System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      
<section name="xmlSerializer" type="System.Xml.Serialization.Configuration.XmlSerializerSection, System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      
</sectionGroup>
 
 
 
 
  
<system.xml.serialization>
     
<schemaImporterExtensions>
            
<add name="dataTableSchemaImporterExtension" type="Xrinehart.Tools.WebService.SchemaImporter.DataTableSchemaImporterExtension, Xrinehart.Tools.WebService.SchemaImporter,Version=1.0.0.0,Culture=neutral,PublicKeyToken=5a627ce15fb94702" />
    
</schemaImporterExtensions>
 
</system.xml.serialization>


  完成以上的步骤后,再编译WebService,重新引用(或者更新Web引用),就可以正确的识别DataTable类型了。
  其实DataTable只实现了序列化,但WebService并不能自己反序列化为可识别的格式,所以需要自己手动增加。由此可以衍生为各种业务实体BussinessEntity类对象也可以通过以上方式实现直接传递。

  希望对大家有所帮助。

Feedback

#1楼   回复  引用  查看    

2006-08-20 21:19 by livesite      
不建议这种做法,会影响跨平台能力的

#2楼[楼主]   回复  引用  查看    

2006-08-20 21:27 by 風語者·疾風      
呵呵,关于WebService到底是否应该传递DataSet/DataTable这类问题不在这个讨论话题内。不可否认的是,这种做法有大量的项目在使用。
要考虑通用性,大可以把DataTable序列化String来传递。

#3楼   回复  引用  查看    

2006-08-20 22:13 by aspnetx      
难道让消费者逐行解析结果吗?

#4楼   回复  引用    

2006-10-10 19:41 by wx[匿名][未注册用户]
能给个成功的例子吗?我怎么弄不对呢?谢谢

#5楼   回复  引用  查看    

2006-10-16 15:38 by 阿不      
在使用web service返回datatable确实不是很方便。

#6楼   回复  引用    

2008-06-09 08:34 by zf[未注册用户]
需要本地设置?部署不方便了

#7楼   回复  引用    

2008-12-28 00:40 by tongyijie_tongyijie[未注册用户]
可以传datatable的,参数为datatable。xml文件流会自动转换如下:
<?xml version="1.0" encoding="utf-8" ?>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">" target="_new" rel="nofollow">http://www.w3.org/2001/XMLSchema">
- <soap:Body>
- <ImportStationData xmlns="EMAS.WebService">
- <dt>
- <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
- <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="StationObject" msdata:UseCurrentLocale="true">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="StationObject">
- <xs:complexType>
- <xs:sequence>
<xs:element name="StationID" type="xs:string" minOccurs="0" />
<xs:element name="StationName" type="xs:string" minOccurs="0" />
<xs:element name="StationClass" type="xs:string" minOccurs="0" />
<xs:element name="StationFather" type="xs:string" minOccurs="0" />
<xs:element name="StationType" type="xs:string" minOccurs="0" />
<xs:element name="LeftValue" type="xs:string" minOccurs="0" />
<xs:element name="TopValue" type="xs:string" minOccurs="0" />
<xs:element name="GroupID" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
- <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
- <DocumentElement xmlns="">
- <StationObject diffgr:id="StationObject1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
<StationID>1</StationID>
<StationName>?úí|╝ó┐??¥(SS)</StationName>
<StationClass>2</StationClass>
<StationFather>0</StationFather>
<StationType>0</StationType>
<LeftValue>3060</LeftValue>
<TopValue>2655</TopValue>
<GroupID>0</GroupID>
</StationObject>
</dt>
</ImportStationData>
</soap:Body>
</soap:Envelope>



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 481956




相关文章:

相关链接: