前言

系统之间的数据交互往往需要事先定义一些契约,在WCF中我们需要先编写XSD文件,然后通过自动代码生成工具自动生成C#对象。对于刚刚接触契约的人来说,掌握XMLSpy之类的软件之后确实比手写XML效率要高,但还是有些学习成本的。此外XML的tag太多,如果设计的类型属性过多,手写XSD也不太现实,很难专注于设计。

于是我想能不能先用C#写好类型,然后自动生成标准格式的XSD呢。经过三天左右的设计和实现,目前实现了以下功能:

1. 支持Class和Enum类型的设计

2. 支持基元类型、自定义类型、泛型列表、自定义类型数组等属性

3. 支持自定义类型之间的依赖关系

4. 支持契约分组(指定Request/Response分到同一个xsd文件)

5. 支持契约汇总(对于自定义类型,最终体现在一个汇总xsd文件中,并自动引用其它xsd文件)

开源地址:https://github.com/CreateChen/XsdGen。我刚接触SOA不久,目前只添加了xsd的minOccurs、maxOccurs等基本属性,对于其它属性并没有全部集成进去,集成方式也非常简单,在Attribute中添加相应的属性,并在XsdBuilder.cs中添加相应的处理。

效果

先看一下实现的效果,例如我定义了以下类型:FoodOrderRequest、FoodOrderResponse、PayType

using System;
using System.Collections.Generic;
using XsdAttribute; [assembly: XsdSchema(
TargetNamespace = "http://xx.com/framework/soa/sample/v1",
XmlNamespace = "http://xx.com/framework/soa/sample/v1",
Namespace = "http://xx.com/framework/soa/sample/v1",
Common = "http://xx.com/common/types/v1")]
[assembly: XsdImport(Id = "SOACommonTypes",
Namespace = "http://xx.com/common/types/v1",
SchemaLocation = "SOACommonTypes_V1.0.0.xsd")] namespace TestDLL
{
[XsdComplexType(Annotation = "订餐申请", FileGroup = "FoodOrder")]
public class FoodOrderRequest
{
[XsdElement(MinOccurs = "", Annotation = "餐馆编号")]
public int RestaurantId { get; set; } [XsdElement(MinOccurs = "", Annotation = "餐馆名称")]
public string RestaurantName { get; set; } [XsdElement(Annotation = "订餐日期")]
public DateTime OrderDate { get; set; } [XsdElement(MinOccurs = "", MaxOccurs = "unbounded", Annotation = "食品编号")]
public List<int> FoodId { get; set; } [XsdElement(MinOccurs = "", Annotation = "业务类型")]
public PayType BusinessType { get; set; }
} [XsdComplexType(Annotation = "订餐结果", FileGroup = "FoodOrder")]
public class FoodOrderResponse
{
[XsdElement(MinOccurs = "", Annotation = "订单编号")]
public int OrderId { get; set; } [XsdElement(Annotation = "预计送达时间")]
public DateTime DeliveryTime { get; set; }
} [XsdSimpleType(Annotation = "付款类型", FileGroup = "PayType")]
public enum PayType
{
现金,
支付宝,
微信,
网银
}
}

工具自动为我生成了3个文件:

FoodOrder.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="FoodOrder" targetNamespace="http://xx.com/framework/soa/sample/v1" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://xx.com/framework/soa/sample/v1" xmlns:ns="http://xx.com/framework/soa/sample/v1" xmlns:common="http://xx.com/common/types/v1">
<xs:include schemaLocation="PayType.xsd" />
<xs:import id="SOACommonTypes" schemaLocation="SOACommonTypes_V1.0.0.xsd" namespace="http://xx.com/common/types/v1" />
<xs:complexType name="FoodOrderRequestType">
<xs:annotation>
<xs:documentation>订餐申请</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="RestaurantId" type="xs:int" minOccurs="1">
<xs:annotation>
<xs:documentation>餐馆编号</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="RestaurantName" type="xs:string" minOccurs="1">
<xs:annotation>
<xs:documentation>餐馆名称</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="OrderDate" type="xs:dateTime">
<xs:annotation>
<xs:documentation>订餐日期</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="FoodId" type="xs:int" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>食品编号</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="BusinessType" type="PayType" minOccurs="1">
<xs:annotation>
<xs:documentation>业务类型</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="FoodOrderResponseType">
<xs:annotation>
<xs:documentation>订餐结果</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="OrderId" type="xs:int" minOccurs="1">
<xs:annotation>
<xs:documentation>订单编号</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="DeliveryTime" type="xs:dateTime">
<xs:annotation>
<xs:documentation>预计送达时间</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>

PayType.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="PayType" targetNamespace="http://xx.com/framework/soa/sample/v1" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://xx.com/framework/soa/sample/v1" xmlns:ns="http://xx.com/framework/soa/sample/v1" xmlns:common="http://xx.com/common/types/v1">
<xs:import id="SOACommonTypes" schemaLocation="SOACommonTypes_V1.0.0.xsd" namespace="http://xx.com/common/types/v1" />
<xs:simpleType name="PayType" final="restriction">
<xs:restriction base="xs:string">
<xs:enumeration value="现金" />
<xs:enumeration value="支付宝" />
<xs:enumeration value="微信" />
<xs:enumeration value="网银" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

TestDLL.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="TestDLL" targetNamespace="http://xx.com/framework/soa/sample/v1" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://xx.com/framework/soa/sample/v1" xmlns:ns="http://xx.com/framework/soa/sample/v1" xmlns:common="http://xx.com/common/types/v1">
<xs:import id="SOACommonTypes" schemaLocation="SOACommonTypes_V1.0.0.xsd" namespace="http://xx.com/common/types/v1" />
<xs:include schemaLocation="FoodOrder.xsd" />
<xs:include schemaLocation="PayType.xsd" />
<xs:element name="FoodOrderRequest" nillable="true" type="ns:FoodOrderRequestType" />
<xs:element name="FoodOrderResponse" nillable="true" type="ns:FoodOrderResponseType" />
</xs:schema>

自定义Attribute

1. Assembly的Attribute

[AttributeUsage(AttributeTargets.Assembly)]
public class XsdSchema : Attribute
{
public string TargetNamespace { get; set; }
public string XmlNamespace { get; set; }
public string Namespace { get; set; }
public string Common { get; set; } //汇总dll中的类型,生成总的xsd
private string _packageId;
/// <summary>
/// 生成XSD的文件名称
/// </summary>
public string PackageId
{
get { return _packageId; }
set
{
//去除文件名中非法字符
var regex = new Regex(@"\:|\;|\/|\\|\||\,|\*|\?|\""|\<|\>");
_packageId = regex.Replace(value, "");
}
} public static XsdSchema Get(Assembly assembly)
{
return (XsdSchema) GetCustomAttribute(assembly, typeof (XsdSchema));
}
}

前几个是一些命名空间的定义,可以根据自己公司的业务规则进行设计。默认情况下,汇总文件的targetId、文件名称以及生成的文件夹名称都是PackageId决定,如果dll没有指定该值,默认则是dll的Name。

除了定义Schema,每个xsd文件中可能还需要导入一些默认的公共类型,在这种情况下,可以为assembly添加如下Attribute:

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class XsdImport : Attribute
{
public string Id { get; set; }
public string SchemaLocation { get; set; }
public string Namespace { get; set; } public static IEnumerable<XsdImport> Get(Assembly assembly)
{
var attributes = GetCustomAttributes(assembly, typeof (XsdImport));
return attributes.Cast<XsdImport>();
}
}

2. Class类型的Attribute

[AttributeUsage((AttributeTargets.Class))]
public class XsdComplexType : Attribute
{
private string _fileGroup; /// <summary>
/// 生成XSD的文件名称
/// </summary>
public string FileGroup
{
get { return _fileGroup; }
set
{
//去除文件名中非法字符
var regex = new Regex(@"\:|\;|\/|\\|\||\,|\*|\?|\""|\<|\>");
_fileGroup = regex.Replace(value, "");
}
} public string Annotation { get; set; } public static XsdComplexType Get(Type type)
{
return (XsdComplexType) GetCustomAttribute(type, typeof (XsdComplexType));
}
}

其中必须指定FileGroup值,相同的FileGroup值,最后会生成到同一个xsd文件中。

2. Property的Attribute

[AttributeUsage((AttributeTargets.Property))]
public class XsdElement : Attribute
{
public string MinOccurs { get; set; }
public string MaxOccurs { get; set; }
public string Annotation { get; set; } public static XsdElement Get(PropertyInfo propertyInfo)
{
return (XsdElement) GetCustomAttribute(propertyInfo, typeof (XsdElement));
}
}

如果自定义类型的属性是List或者Array,要将MaxOccurs设为大于0的数或者unbounded。

3. Enum类型的Attribute

[AttributeUsage((AttributeTargets.Enum))]
public class XsdSimpleType : Attribute
{
private string _fileGroup; /// <summary>
/// 生成XSD的文件名称
/// </summary>
public string FileGroup
{
get { return _fileGroup; }
set
{
//去除文件名中非法字符
var regex = new Regex(@"\:|\;|\/|\\|\||\,|\*|\?|\""|\<|\>");
_fileGroup = regex.Replace(value, "");
}
} public string Annotation { get; set; } public static XsdSimpleType Get(Type type)
{
return (XsdSimpleType) GetCustomAttribute(type, typeof (XsdSimpleType));
}
}

与XsdComplexType类似,相同的FileGroup类型,最后都归到同一个xsd文件中。

反射DLL并生成XSD

1. XsdFile结构定义

public class XsdFile
{
public XsdFile()
{
Imports = new List<XElement>();
Elements = new List<XElement>();
} public XElement Schema { get; set; } /// <summary>
/// <para>Assembly级别的Import</para>
/// <para>自定义复合对象的Import</para>
/// </summary>
public List<XElement> Imports { get; set; } /// <summary>
/// <para>自定义Class类型</para>
/// <para>自定义枚举类型</para>
/// </summary>
public List<XElement> Elements { get; set; } public XElement ToXML()
{
foreach (var import in Imports)
{
Schema.Add(import);
}
foreach (var element in Elements)
{
Schema.Add(element);
}
return Schema;
}
}

基本思路是Schema添加所有的Import和Element,最后生成XML。

2. XsdBuilder

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using XsdAttribute; namespace XsdGen
{
public class XsdBuilder
{
private readonly XNamespace _xs = "http://www.w3.org/2001/XMLSchema";
private Assembly _assembly; //Key:FileGroup, Value:对应的XsdFile
private Dictionary<string, XsdFile> _xsdFiles; //自定义Class对象的声明,用于生成汇总xsd
private List<XElement> _elements; public void Build(Assembly assembly)
{
_assembly = assembly;
_xsdFiles = new Dictionary<string, XsdFile>();
_elements = new List<XElement>(); XElement[] defaultImports = GetDefaultImports(_assembly).ToArray();
XsdSchema defaultSchema = XsdSchema.Get(_assembly); string directoryName = defaultSchema.PackageId ?? _assembly.GetName().Name;
if (!Directory.Exists(directoryName))
{
Directory.CreateDirectory(directoryName);
} BuildTypes(_assembly);
foreach (var item in _xsdFiles)
{
item.Value.Schema = GetSchema(defaultSchema, item.Key);
foreach (var import in defaultImports)
{
item.Value.Imports.Add(import);
}
//生成XSD文件
string fileName = string.Format("{0}/{1}.xsd", directoryName, item.Key);
item.Value.ToXML().Save(fileName);
Console.WriteLine("Generate {0}", fileName);
}
//生成汇总XSD文件
var summaryXsdFile = BuildSummary(defaultSchema, defaultImports, directoryName);
string summaryXsdFileName = string.Format("{0}/{1}.xsd", directoryName, directoryName);
summaryXsdFile.ToXML().Save(summaryXsdFileName);
Console.WriteLine("{0}Generate Summary{0}\n{1}", new String('=', ), summaryXsdFileName);
} private XElement GetSchema(XsdSchema xsdSchema, string id)
{
var schema = new XElement(
_xs + "schema",
new XAttribute("id", id),
new XAttribute("targetNamespace", xsdSchema.TargetNamespace),
new XAttribute("elementFormDefault", "qualified"),
new XAttribute("attributeFormDefault", "unqualified"),
new XAttribute(XNamespace.Xmlns + "xs", _xs.ToString())
);
if (!string.IsNullOrEmpty(xsdSchema.XmlNamespace))
schema.SetAttributeValue("xmlns", xsdSchema.XmlNamespace);
if (!string.IsNullOrEmpty(xsdSchema.Namespace))
schema.SetAttributeValue(XNamespace.Xmlns + "ns", xsdSchema.Namespace);
if (!string.IsNullOrEmpty(xsdSchema.Common))
schema.SetAttributeValue(XNamespace.Xmlns + "common", xsdSchema.Common);
return schema;
} private IEnumerable<XElement> GetDefaultImports(Assembly assembly)
{
var xsdImports = XsdImport.Get(assembly); return xsdImports.Select(xsdImport => new XElement(
_xs + "import",
new XAttribute("id", xsdImport.Id),
new XAttribute("schemaLocation", xsdImport.SchemaLocation),
new XAttribute("namespace", xsdImport.Namespace)
));
} private void BuildTypes(Assembly assembly)
{
var types = assembly.GetTypes();
foreach (var type in types)
{
string fileGroup;
if (type.IsClass)
{
var element = BuildElement(type);
_elements.Add(element);
//_xsdFiles[fileGroup].Elements.Add(element); var complexTypeElement = BuildComplexType(type, out fileGroup);
_xsdFiles[fileGroup].Elements.Add(complexTypeElement);
}
else if (type.IsEnum)
{
var simpleTypeElement = BuildSimpleType(type, out fileGroup);
_xsdFiles[fileGroup].Elements.Add(simpleTypeElement);
}
}
} public XElement BuildElement(Type type)
{
//只有Request或者Response对象类型,末尾自动添加Type
string name = (type.Name.EndsWith("Request") || type.Name.EndsWith("Response"))
? type.Name + "Type"
: type.Name; return new XElement(
_xs + "element",
new XAttribute("name", type.Name),
new XAttribute("nillable", true),
new XAttribute("type", "ns:" + name)
);
} private XElement BuildComplexType(Type type, out string fileGroup)
{
var xsdComplexType = XsdComplexType.Get(type);
//添加XSD文件
fileGroup = xsdComplexType.FileGroup;
SetDefaultFile(fileGroup); //只有Request或者Response对象类型,末尾自动添加Type
string name = (type.Name.EndsWith("Request") || type.Name.EndsWith("Response"))
? type.Name + "Type"
: type.Name; var complexTypeElement = new XElement(
_xs + "complexType",
new XAttribute("name", name)
); if (!string.IsNullOrEmpty(xsdComplexType.Annotation))
{
complexTypeElement.Add(new XElement(
_xs + "annotation",
new XElement(_xs + "documentation", xsdComplexType.Annotation)
));
} var sequenceElement = BuildSequence(type);
AddProperties(type, sequenceElement);
complexTypeElement.Add(sequenceElement);
return complexTypeElement;
} private XElement BuildSequence(Type type)
{
var sequence = new XElement(_xs + "sequence");return sequence;
} private XsdFile BuildSummary(XsdSchema defaultSchema, XElement[] defaultImports, string packageId)
{
XsdFile xsdFile = new XsdFile();
xsdFile.Schema = GetSchema(defaultSchema, packageId);
foreach (var import in defaultImports)
{
xsdFile.Imports.Add(import);
}
//include所有其它自动生成的xsd文件
foreach (var item in _xsdFiles)
{
xsdFile.Imports.Add(new XElement(
_xs + "include",
new XAttribute("schemaLocation", item.Key + ".xsd")
));
}
//添加dll中所有定义的element
foreach (var item in _elements)
{
xsdFile.Elements.Add(item);
}
return xsdFile;
} private void AddProperties(Type type, XElement sequenceElement)
{
var properties = type.GetProperties();
foreach (var propertyInfo in properties)
{
var typeName = Common.GetXsdTypeName(propertyInfo.PropertyType);
var propertyElement = new XElement(
_xs + "element",
new XAttribute("name", propertyInfo.Name),
new XAttribute("type", typeName)
); var xsdElement = XsdElement.Get(propertyInfo);
if (xsdElement != null)
{
if (!string.IsNullOrEmpty(xsdElement.MinOccurs))
propertyElement.SetAttributeValue("minOccurs", xsdElement.MinOccurs);
if (!string.IsNullOrEmpty(xsdElement.MaxOccurs))
propertyElement.SetAttributeValue("maxOccurs", xsdElement.MaxOccurs); if (!string.IsNullOrEmpty(xsdElement.Annotation))
propertyElement.Add(new XElement(
_xs + "annotation",
new XElement(
_xs + "documentation", xsdElement.Annotation
)
));
} //判断是否自定义类型, 添加Import
if (!typeName.StartsWith("xs:"))
{
var parentClassFileGroup = XsdComplexType.Get(type).FileGroup;
var propertyClassFileGroup = Common.GetFileGroup(propertyInfo.PropertyType);
if (parentClassFileGroup != propertyClassFileGroup)
{
string importXsd = propertyClassFileGroup + ".xsd";
//判断是否已经存在该Import
if (_xsdFiles[parentClassFileGroup].Imports.All(item => item.Attribute("schemaLocation").Value != importXsd))
{
_xsdFiles[parentClassFileGroup].Imports.Add(
new XElement(
_xs + "include",
new XAttribute("schemaLocation", importXsd)
)
);
}
}
}
sequenceElement.Add(propertyElement);
}
} private XElement BuildSimpleType(Type type, out string fileGroup)
{
var xsdSimpleType = XsdSimpleType.Get(type);
//添加XSD文件
fileGroup = xsdSimpleType.FileGroup;
SetDefaultFile(fileGroup); var simpleTypeElement = new XElement(
_xs + "simpleType",
new XAttribute("name", type.Name),
new XAttribute("final", "restriction")
);
var restrictionElement = new XElement(
_xs + "restriction",
new XAttribute("base", "xs:string")
); foreach (var val in Enum.GetNames(type))
{
restrictionElement.Add(
new XElement(
_xs + "enumeration",
new XAttribute("value", val)
)
);
}
simpleTypeElement.Add(restrictionElement);
return simpleTypeElement;
} private void SetDefaultFile(string fileGroup)
{
if (!_xsdFiles.ContainsKey(fileGroup))
{
var xsdFile = new XsdFile();
_xsdFiles[fileGroup] = xsdFile;
}
}
}
}

XsdBuilder依次反射出Assembly、Class、Enum、Property的自定义Attribute,根据XSD的规则构造XElement。主要步骤在Builder函数中都有所体现。

应用

现在写接口契约就很爽了,只要定义好类生成DLL,通过XsdGen.exe就可轻松生成接口契约

参考

http://www.codeproject.com/Articles/2933/Attributes-in-C

https://msdn.microsoft.com/en-us/library/84c42s56%28v=vs.110%29.aspx

https://msdn.microsoft.com/en-us/library/aa719879(v=vs.71).aspx

https://msdn.microsoft.com/en-us/library/y1375e30%28v=vs.110%29.aspx

http://stackoverflow.com/questions/3353699/using-reflection-to-get-all-classes-of-certain-base-type-in-dll

http://stackoverflow.com/questions/1936953/custom-assembly-attributes

http://stackoverflow.com/questions/1168532/xsd-definition-for-enumerated-value

https://msdn.microsoft.com/en-us/library/bb387075.aspx

XsdGen:通过自定义Attribute与反射自动生成XSD的更多相关文章

  1. 利用Vistual Studio自带的xsd.exe工具,根据XML自动生成XSD

    利用Vistual Studio自带的xsd.exe工具,根据XML自动生成XSD 1, 命令提示符-->找到vs自带的xsd.exe工具所在的文件夹 例如: C:\Program Files ...

  2. wpf 通过为DataGrid所绑定的数据源类型的属性设置Attribute改变DataGrid自动生成列的顺序

    环境Win10 VS2019 .Net Framework4.8 在wpf中,如果为一个DataGrid绑定到一个数据源,默认情况下DataGrid会为数据源类型的每个属性生成一个列(Column)对 ...

  3. 根据xml文件自动生成xsd文件

    根据xml生成xsd文档 1. 找到vs自带的xsd.exe工具所在的文件夹位置: C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin 注意 ...

  4. 利用反射自动生成SQL语句(仿Linq)

    转:http://www.cnblogs.com/the7stroke/archive/2012/04/22/2465597.html using System; using System.Colle ...

  5. [goa]golang微服务框架学习(二)-- 代码自动生成

    之前用过go语言的反射来做一些代码生成,参考这篇. 但是这种方式,入侵太强,需要执行对应的申明调用, 所以对GOA框架的自动生成非常感兴趣,于是仔细研究了一下,发现用的比较巧妙, 这里先卖个关子,先看 ...

  6. 如何由XSD自动生成XML和实体类

    项目中有时候要用XML作为数据源,因此需要定义XML文件和相应的类,最佳方法是首先定义XSD,然后自动生成实体类,最后生成XML和填充数据:读取XML数据源的时候,首先用XSD验证XML数据格式,然后 ...

  7. Java利用自定义注解、反射实现简单BaseDao

    在常见的ORM框架中,大都提供了使用注解方式来实现entity与数据库的映射,这里简单地使用自定义注解与反射来生成可执行的sql语句. 这是整体的目录结构,本来是为复习注解建立的项目^.^ 好的,首先 ...

  8. 反射实体自动生成EasyUi DataGrid模板 第二版--附项目源码

    之前写过一篇文章,地址 http://www.cnblogs.com/Bond/p/3469798.html   大概说了下怎么通过反射来自动生成对应EasyUi datagrid的模板,然后贴了很多 ...

  9. 反射实体自动生成EasyUi DataGrid模板

    用EasyUi Datagrid展示数据的时候总是要一下这样一段代码 <table id="dt" class="easyui-datagrid"> ...

随机推荐

  1. 实战录 | Redis的主从服务器搭建

    <实战录>导语 云端卫士<实战录>栏目定期会向粉丝朋友们分享一些在开发运维中的经验和技巧,希望对于关注我们的朋友有所裨益.本期分享人为云端卫士安全平台工程师田全磊,将带来Red ...

  2. noip2014-day1-t2

    题目描述:无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离. ...

  3. Python成长笔记 - 基础篇 (二)python基本语法

    Python的设计目标之一是让代码具备高度的可阅读性.它设计时尽量使用其它语言经常使用的标点符号和英文单字,让代码看起来整洁美观.它不像其他的静态语言如C.Pascal那样需要重复书写声明语句,也不像 ...

  4. PHPCMS联动菜单的调用函数get_linkage方法详解

    v9联动菜单调用方法[注意此为内容页调用方法 {get_linkage($areaid,1,' >> ',1)} 显示效果: 湖北省 >> 武汉市 >> 汉阳区 [ ...

  5. UIAlertView、 UIActionSheet

    一.UIAlertView. UIActionSheet都是ios系统自带的弹出式对话框,当UIAlertView或UIActionSheet弹出来时用户无法与应用界面中的其它控件交互,UIAlert ...

  6. MariaDB5.5(mysql)的partitioning设置 for Zabbix3.0

    用zabbix的同学都知道,一台服务器监视几百几千台服务器,一个服务器几十个item,长年下来数据量是很惊人的. 而zabbix自带的housekeeping功能,默认状态下的删除速度完全跟不上数据增 ...

  7. 后台向前台输出 换行“\n”

    MVC 中后台向前台输出 "\n"总是报错 因为后台向前台输出 "\n" 后,前台出现换行  eg: "这里是\n换行" var str=& ...

  8. 深入理解java虚拟机【Java虚拟机类生命周期】

    C/C++等纯编译语言从源码到最终执行一般要经历:编译.连接和运行三个阶段,连接是在编译期间完成,而java在编译期间仅仅是将源码编译为Java虚拟机可以识别的字节码Class类文件,Java虚拟机对 ...

  9. jenkins插件 查看job下次运行时间

    文章来自:http://www.ciandcd.com 文中的代码来自可以从github下载: https://github.com/ciandcd jenkins插件next executions( ...

  10. 到底是 const 还是 static readonly

    真的一样? const 和 static readonly 常在程序中用来声明常量,调用方法也没有什么不同,他们真的一样吗?我们可以做个试验. 程序集内的常量 现在我们建立一个程序,里面有一个MyCl ...