- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我一直在尝试将 GeoJSON 映射到 C# DataContracts,以便我们能够轻松地支持在我们的 WCF/REST-api 中返回 GeoJSON。我越多地使用 DataContracts 和序列化,我就越觉得这是一个我无法理解的魔法黑匣子。
无论如何,这是我目前为止:
namespace GeoJSON {
[DataContract]
[KnownType(typeof (Point))]
[KnownType(typeof (MultiPoint))]
[KnownType(typeof (LineString))]
[KnownType(typeof (MultiLineString))]
[KnownType(typeof (Polygon))]
[KnownType(typeof (MultiPolygon))]
[KnownType(typeof (Feature))]
[KnownType(typeof (FeatureCollection))]
[KnownType(typeof (Geometry))]
[KnownType(typeof(GeometryCollection))]
public abstract class GeoJson {
// This is because WCF services can't read the DataContracts KnownType's above
// so you need to break DRY and repeat yourself here and add this class
// to a ServiceKnownType-attribute to every service method returning GeoJSON
// Like this:
// [ServiceKnownType("Types", typeof(GeoJson.KnownTypes))]
public static class KnownTypes {
public static Type[] Types(ICustomAttributeProvider provider) {
return new[] {
typeof (Point),
typeof (MultiPoint),
typeof (LineString),
typeof (MultiLineString),
typeof (Polygon),
typeof (MultiPolygon),
typeof (Feature),
typeof (FeatureCollection),
typeof (Geometry),
typeof (GeometryCollection)
};
}
}
}
#region Feature
// The idea here (and elsewhere) is that if i let the type field be enums the
// deserializer might use that information to chose the right class.
// Is this just crack?
[DataContract]
public enum FeatureType {
[EnumMember] Feature
}
public class Feature : GeoJson {
public Feature() {
Type = FeatureType.Feature;
Properties = new Dictionary<string, string>();
}
public Feature(Geometry geometry) {
Type = FeatureType.Feature;
Properties = new Dictionary<string, string>();
Geometry = geometry;
}
[DataMember(Name = "type")]
public FeatureType Type { get; set; }
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(IsRequired = true, Name = "geometry")]
public Geometry Geometry { get; set; }
// TODO: Make this support proper JSON-trees
[DataMember(IsRequired = true, Name = "properties")]
public IDictionary<string, string> Properties { get; set; }
}
#endregion Feature
#region FeatureCollection
[DataContract]
public enum FeatureCollectionType {
[EnumMember]
FeatureCollection
}
[DataContract(Name = "FeatureCollection")]
public class FeatureCollection : GeoJson {
public FeatureCollection() {
Type = FeatureCollectionType.FeatureCollection;
Features = new Feature[0];
}
public FeatureCollection(params Feature[] features) {
Type = FeatureCollectionType.FeatureCollection;
Features = features ?? new Feature[0];
}
[DataMember(Name = "type")]
private FeatureCollectionType Type { get; set; }
[DataMember(Name = "features", IsRequired = true)]
private Feature[] Features { get; set; }
}
#endregion FeatureCollection
#region GeometryCollection
[DataContract]
public enum GeometryCollectionType {
[EnumMember] GeometryCollection
}
[DataContract(Name = "GeometryCollection")]
public class GeometryCollection : GeoJson {
public GeometryCollection() {
Type = GeometryCollectionType.GeometryCollection;
Geometries = new Geometry[0];
}
public GeometryCollection(params Geometry[] geometries) {
Type = GeometryCollectionType.GeometryCollection;
Geometries = geometries ?? new Geometry[0];
}
[DataMember(Name = "type")]
private GeometryCollectionType Type { get; set; }
[DataMember(Name = "geometries", IsRequired = true)]
private Geometry[] Geometries { get; set; }
}
#endregion GeometryCollection
#region Geometry
/* TODO:
* - More constructors
* - Enforce some more invariants.
*/
[DataContract]
[KnownType(typeof(Point))]
[KnownType(typeof(MultiPoint))]
[KnownType(typeof(LineString))]
[KnownType(typeof(MultiLineString))]
[KnownType(typeof(Polygon))]
[KnownType(typeof(MultiPolygon))]
public abstract class Geometry : GeoJson { }
[DataContract]
public enum PointType {
[EnumMember(Value="Point")] Point
}
[DataContract]
public class Point : Geometry {
public Point() {
Type = PointType.Point;
}
[DataMember(Name = "type", Order = 0)]
public PointType Type { get; set; }
[DataMember(Name = "coordinates", Order = 1)]
public double[] Coordinates { get; set; }
}
[DataContract]
public enum MultiPointType {
[EnumMember(Value = "MultiPoint")] MultiPoint
}
[DataContract]
public class MultiPoint : Geometry {
public MultiPoint() {
Type = MultiPointType.MultiPoint;
}
[DataMember(Name = "type", Order = 0)]
public MultiPointType Type { get; set; }
[DataMember(Name = "coordinates", Order = 1)]
public double[][] Coordinates { get; set; }
}
[DataContract]
public enum LineStringType {
[EnumMember] LineString
}
[DataContract]
public class LineString : Geometry {
public LineString() {
Type = LineStringType.LineString;
}
[DataMember(Name = "type", Order = 0)]
public LineStringType Type { get; set; }
[DataMember(Name = "coordinates", Order = 1)]
public double[] Coordinates { get; set; }
}
[DataContract]
public enum MultiLineStringType {
[EnumMember] MultiLineString
}
[DataContract]
public class MultiLineString : Geometry {
public MultiLineString() {
Type = MultiLineStringType.MultiLineString;
}
[DataMember(Name = "type", Order = 0)]
public MultiLineStringType Type { get; set; }
[DataMember(Name = "coordinates", Order = 1)]
public double[][] Coordinates { get; set; }
}
[DataContract]
public enum PolygonType {
[EnumMember] Polygon
}
[DataContract]
public class Polygon : Geometry {
public Polygon() {
Type = PolygonType.Polygon;
}
[DataMember(Name = "type", Order = 0)]
public PolygonType Type { get; set; }
[DataMember(Name = "coordinates", Order = 1)]
public double[][] Coordinates { get; set; }
}
[DataContract]
public enum MultiPolygonType {
[EnumMember] MultiPolygon
}
[DataContract]
public class MultiPolygon : Geometry {
public MultiPolygon() {
Type = MultiPolygonType.MultiPolygon;
}
[DataMember(Name = "type", Order = 0)]
public MultiPolygonType Type { get; set; }
[DataMember(Name = "coordinates", Order = 1)]
public double[][][] Coordinates { get; set; }
}
#endregion Geometry
}
namespace Test {
internal class Program {
private static void Main(string[] args) {
var linestring = new LineString {
Coordinates = new[] {12.0, 57.1, 13, 14}
};
var point = new Point {
Coordinates = new[] { 12.0, 57.1 }
};
var geometryCollection = new GeometryCollection(point, linestring);
var feature = new Feature(linestring);
var featureCollection = new FeatureCollection(
feature,
new Feature(point)
);
try {
WriteObject("LineString", linestring);
WriteObject("Point", point);
WriteObject("GeometryCollection",geometryCollection);
WriteObject("Feature", feature);
WriteObject("FeatureCollection", featureCollection);
}
catch (Exception ex) {
Console.WriteLine("An exception occured: " + ex.Message);
}
Console.ReadKey();
}
public static void WriteObject(string label, GeoJson json) {
var stream = new MemoryStream();
var ser = new DataContractJsonSerializer(json.GetType());
ser.WriteObject(stream, json);
stream.Position = 0;
var sr = new StreamReader(stream);
Console.Write("\n" + label + ":\n\t");
Console.WriteLine(sr.ReadToEnd());
}
}
}
LineString:
{"type":0,"coordinates":[12,57.1,13,14]}
Point:
{"type":0,"coordinates":[12,57.1]}
GeometryCollection:
{"geometries":[{"__type":"Point:#GeoJSON","type":0,"coordinates":[12,57.1]},{"__type":"LineString:#GeoJSON","type":0,"coordinates":[12,57.1,13,14]}],"type":0}
Feature:
{"geometry":{"__type":"LineString:#GeoJSON","type":0,"coordinates":[12,57.1,13,14]},"id":null,"properties":[],"type":0}
FeatureCollection:
{"features":[{"geometry":{"__type":"LineString:#GeoJSON","type":0,"coordinates":[12,57.1,13,14]},"id":null,"properties":[],"type":0},{"geometry":{"__type":"Point:#GeoJSON","type":0,"coordinates":[12,57.1]},"id":null,"properties":[], "type":0}],"type":0}
在 WCF 服务中使用它们时,我也遇到了这些问题。有任何想法吗?关于我是否会反序列化这个问题或者这个想法是否合理的任何提示?
最佳答案
我可以肯定地说,没有办法绕过 __type 排放,除非您不在多态场景中序列化该类型。
一种可能的解决方案是创建某种不会调用多态性的包装操作,并通过该操作而不是通过 poly 方法返回对象。
JSON 序列化程序确实有一个名为 alwaysEmitTypeInformation 的标志,但您打开它可以始终发出 __type。现在有办法将其关闭,主要是为了避免无意的用户错误。
另请参阅我的回答:Rename __type-field in WCF services
关于c# - C# DataContracts 的表现力是否足以正确描述 GeoJSON?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9327483/
是否有可能(如果可以,那么如何)从未实现 [DataContract] 的基类继承并告诉序列化程序忽略它? 有点像 //Non-accessible, non-[DataContract] class
问题是我没有得到我想要的 XML 结构。我的代码如下: [DataContract] public class Persons { [DataMember] public List P
下面是我的 WCF DataContract 基类 [DataContract] public class BaseClass { //some datamember
WCF 新手。 DataContact 类可以继承自 Interface 吗? 例如: [DataContract(Namespace = ...........)] public class Ves
我有一个令人沮丧的问题,我一直在努力克服但似乎无法弄清楚。 我有通过 WCF 中的 SOAP 和 REST 端点公开的服务。为了避免重复的对象代码,我想在两个服务之间重用契约(Contract)对象。
好吧,这里什么都没有。在阅读了服务版本控制和数据契约(Contract)版本控制的最佳实践 (http://msdn.microsoft.com/en-us/library/ms733832.aspx
我想知道通过 WCF 服务公开哪些对象有什么意义 - 我应该将 WCF 序列化规范添加到我的业务实体,还是应该实现一个转换器将我的业务实体映射到我想通过我的 WCF 公开的 DataContracts
[DataMember] public int? NumberOfPages; //////////// Is this supported???? [DataMember]
我有一个 ServiceContract,它有一个具有以下方法签名的 OperationContract:Manipulate(int fileid, param object[] Operation
我有一个类(带有属性和一些方法) [DataContract] public partial class AbstractApplicationCallDto { [IgnoreDataMem
我想使用 AJAX 调用来使用 WCF REST 服务。 假设我有以下内容 Person是一个用户定义的类: [ServiceContract] public interface IPerson {
我一直在阅读有关在我的 Silverlight 项目中有一个 [DataContract] 指定类的信息。我知道它们被序列化并传递给客户端以传递信息。 除此之外,您似乎可以在某些情况下向这些类添加代码
基本上我有一个 DataContract,其中包含一个 Dictionary: [DataContract] public class MyDictionary : IDictionary {
我上过这样的课: [DataContract(Namespace = "blah")] public class Item { [DataMember(Order = 0)] publ
我知道当你创建一个服务时你可以创建一个通用的 DataContract: [DataContract(Name = "Get{0}Request") public sealed class GetIt
我正在尝试将类 B 序列化为 ita 基类 A 的实例。 DataContractSerializer 不允许我这样做。 序列化失败的例子如下: class Program { [DataCo
我的数据最好被描述为“洋葱状”,因为每个外层都建立在它下面的一层之上。下面您将看到一个大大简化的版本(我的版本更深几层,但在每一层都表现出相同的行为)。 [CollectionDataContract
我正在设置 WCF 界面。我的数据契约(Contract)如下所示: [DataContract(Namespace = "wcf")] [KnownType(typeof(TypeFromLibra
我的数据最好被描述为“洋葱状”,因为每个外层都建立在它下面的一层之上。下面您将看到一个大大简化的版本(我的版本更深几层,但在每一层都表现出相同的行为)。 [CollectionDataContract
我不知道使用的是什么序列化程序,但在使用 datacontract 属性的 Name 属性时,我在序列化过程中看到了一些不一致的行为。 这是我正在做的一个例子: [XmlRoot(ElementNam
我是一名优秀的程序员,十分优秀!