我正在使用CodeDOM从几个xsd文件构建代码。因此,假设我们有一些映射,从xsd中定义的名称空间到已经创建的程序集中的名称空间:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:abw="MyNamespace" xmlns:bfm="BaseNamespace"
xmlns:gml="http://www.opengis.net/gml/3.2" elementFormDefault="qualified" targetNamespace="MyNamespace"
version="1.0.1.0">
<import namespace="BaseNamespace" schemaLocation="Base.xsd"/>
<import namespace="http://www.opengis.net/gml/3.2" schemaLocation="http://schemas.opengis.net/gml/3.2.1/gml.xsd"/>
<element name="MyClass" substitutionGroup="bfm:MyBaseClass" type="abw:MyClassType"/>
<complexType name="MyClassType">
<complexContent>
<extension base="bfm:MyBaseClassType">
<sequence>
<element maxOccurs="unbounded" minOccurs="0" name="Property1" type="gml:ReferenceType">
<annotation>
<appinfo>
<targetElement xmlns="http://www.opengis.net/gml/3.2">abw:MyClass2</targetElement>
<reversePropertyName xmlns="http://www.opengis.net/gml/3.2">abw:MyClassAlias</reversePropertyName>
</appinfo>
</annotation>
</element>
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
现在 - 由于命名空间BaseNamespace
和gml
的程序集已经存在 - 我只想构建MyClass
的源代码,它应该自动引用基类{{ 1}}和bfm:MyBaseClass
添加gml:ReferenceType
- 指令。
所以我为using
创建了CodeNamespace
,它从xsd应用了名称空间targetNamespace
。现在我循环MyNamespace
中的类型并过滤我的xsd中存在的类型,因为所引用的xsd文件中的所有其他类型已经已经分配给它们的程序集。如果我的xsd中未定义类型,则应将 not 添加到代码中,但应添加CodeNamespace
。
using
medthod var codeNamepscace = new CodeNamespace("targetNamepscae");
var tmp = code.Types.Cast<CodeTypeDeclaration>().ToArray();
foreach (var type in tmp)
{
var typeFromSchema = schema.SchemaTypes.Names.Cast<XmlQualifiedName>().FirstOrDefault(x => x.Name == type.Name);
if (typeFromSchema == null)
{
string xsdNamespace = ???; // how to get the xsd-namespace for the current type here?
Console.WriteLine(String.Format("Found referenced type {0} which is not declared in current schema", type.Name));
// omit the type from the current namespace and add a using-directive to the generated source-file if not yet done
code.Types.Remove(type);
// add a using-directive for the type if not already done
if (!((IList)code.Imports).Contains(typeFromSchema.Namespace)) code.Imports.Add(new CodeNamespaceImport(GetDotNetNSFromXsdNS(xsdNamespace)));
}
}
定义了从xsd-files中定义的名称空间到程序集内的名称空间的映射。
我现在的问题是:我如何从xsd中为GetDotNetNSFromXsdNS
中的类型获取命名空间?特别是:如何从生成中排除CodeNamepspace
和gml:ReferenceType
并通过bfm:MyBaseClass
添加它们?
答案 0 :(得分:0)
以下解决方案适合我 - 虽然我认为它更像是一种解决方法:
var tmp = code.Types.Cast<CodeTypeDeclaration>().ToArray(); // temp. copy of our types-list to avoid ModifiedException during iteration
foreach (var type in tmp)
{
var attributes = type.CustomAttributes.Cast<CodeAttributeDeclaration>().Where(x => x.Name.StartsWith("System.Xml.Serialization"));
var namespaceAttribute = attributes.SelectMany(x => x.Arguments.Cast<CodeAttributeArgument>()).FirstOrDefault(x => x.Name == "Namespace");
string xsdNamespace = ((CodePrimitiveExpression)namespaceAttribute.Value).Value as string;
if (xsdNamespace != schema.TargetNamespace)
{
Console.WriteLine("INFO: Found referenced type {0} which is not declared in current schema", type.Name);
// omit the type from the current namespace and add a using-directive to the generated source-file if not yet done
code.Types.Remove(type);
var nameWithinAssembly = this.m_typeMapper.GetDotNetNamespaceFromXsdNamespace(xsdNamespace);
// add a using-directive for the type if not already done
if (!(code.Imports.Cast<CodeNamespaceImport>().Any(x => x.Namespace == nameWithinAssembly))) code.Imports.Add(new CodeNamespaceImport(nameWithinAssembly));
}
}
这里我们假设来自xsd的命名空间在序列化属性中被镜像。因此,我们为ozur CustomAttributes
中的每个类型获取CodeNameapace
,并检查它是否具有Namespace
- 来自System.Xml.Serialization
的任何属性的using
属性。最后,我们要做的就是检查用于序列化的命名空间是否等于schemas target-namespace。如果这个条件没有通过,那么应该使用timeout
- 指令推断出类型,该指令是用最后一行完成的。