static void GenTsApi()
{
string dir = "\\Storage Card";
//string apiTypeFileName = root+Path.DirectorySeparatorChar+"api.d.ts";
string apiFileName = dir + Path.DirectorySeparatorChar + "api.ts";
Type webService = typeof(MES.PDA.WebService);
//获取WebService方法
MethodInfo[] methods = webService.GetMethods(BindingFlags.Instance
| BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.DeclaredOnly);
Type asyncType = typeof(IAsyncResult);
StringBuilder api = new StringBuilder();
api.Append("namespace webService{\r\n");
api.Append(" /**\r\n");
api.Append(" * @constant\r\n");
api.Append(" * @type {string}\r\n");
api.Append(" * @default\r\n");
api.Append(" */\r\n");
api.Append(" const url = \"http://localhost:11062/WebService.asmx\";\r\n");
api.Append(" /**\r\n");
api.Append(" * @class\r\n");
api.Append(" * @classdesc 服务响应\r\n");
api.Append(" */\r\n");
api.Append(" export class webServiceResponse{\r\n");
api.Append(" /**\r\n");
api.Append(" * @description 错误\r\n");
api.Append(" */\r\n");
api.Append(" error:string;\r\n");
api.Append(" /**\r\n");
api.Append(" * @description 请求响应结果\r\n");
api.Append(" */\r\n");
api.Append(" result:object;\r\n");
api.Append(" }\r\n");
api.Append("\r\n");
api.Append(" /**\r\n");
api.Append(" * @callback 请求回调\r\n");
api.Append(" * @param {webServiceResponse} 响应结果\r\n");
api.Append(" */\r\n");
api.Append(" export interface requestCallback\r\n");
api.Append(" {\r\n");
api.Append(" (rsp:webServiceResponse):void;\r\n");
api.Append(" }\r\n");
api.Append("\r\n");
api.Append(" class SOAPClientWrapper{\r\n");
api.Append(" client:SOAPClient = null;\r\n");
api.Append(" constructor(client:SOAPClient)\r\n");
api.Append(" {\r\n");
api.Append(" this.client = client;\r\n");
api.Append(" }\r\n");
api.Append(" public invoke(method:string,paras:object,rsp:requestCallback):void{\r\n");
api.Append(" let para = new SOAPClientParameters();\r\n");
api.Append(" if(paras)\r\n");
api.Append(" {\r\n");
api.Append(" Object.keys(paras).forEach(p=>para.add(p,paras[p]));\r\n");
api.Append(" }\r\n");
api.Append(" this.client.invoke(method,para,true,(r)=>{\r\n");
api.Append(" if(r.result)\r\n");
api.Append(" {\r\n");
api.Append(" var model = new webService[method+\"Response\"]\r\n");
api.Append(" r.result = Object.assign(model,r.result);\r\n");
api.Append(" }\r\n");
api.Append(" rsp(r);\r\n");
api.Append(" });\r\n");
api.Append(" }\r\n");
api.Append(" static New():SOAPClientWrapper\r\n");
api.Append(" {\r\n");
api.Append(" return new SOAPClientWrapper(new SOAPClient(url));\r\n");
api.Append(" }\r\n");
api.Append(" }\r\n");
api.Append(" export const client = SOAPClientWrapper.New();\r\n");
Dictionary<string, string> req = null;
Dictionary<string, string> rsp = null;
Type xmlElemType = typeof(XmlElementAttribute);
foreach (MethodInfo method in methods)
{
if (method.IsConstructor
//排除异步方法
|| (method.Name.StartsWith("Begin")
&& method.ReturnType == asyncType)) continue;
ParameterInfo[] paras = method.GetParameters();
if (method.Name.StartsWith("End") && paras.Length > 0 && paras[0].ParameterType == asyncType)
continue;
req = new Dictionary<string, string>();
rsp = new Dictionary<string, string>();
api.AppendFormat(" export const {0} = \"{0}\";\r\n", method.Name);
if (method.ReturnType != null && method.ReturnType != typeof(void))
{
string resultName = string.Format("{0}Result", method.Name);
if (method.ReturnTypeCustomAttributes.IsDefined(xmlElemType,false))
{
resultName = (method.ReturnTypeCustomAttributes.GetCustomAttributes(xmlElemType, false)[0] as XmlElementAttribute).ElementName;
}
rsp.Add(resultName, GetTsType(method.ReturnType));
}
foreach (ParameterInfo p in paras)
{
if (p.Attributes == ParameterAttributes.None || (p.Attributes & ParameterAttributes.In) == ParameterAttributes.In)
{
req.Add(p.Name, GetTsType(p.ParameterType));
}
if ((p.Attributes & ParameterAttributes.Out) == ParameterAttributes.Out)
{
rsp.Add(p.Name, GetTsType(p.ParameterType));
}
}
api.AppendFormat(" export class {0}_Request\r\n",method.Name);
api.Append(" {\r\n");
if(req.Count > 0)
{
api.Append(string.Join("", req.Select(kv => string.Format(" {0}:{1};\r\n", kv.Key, kv.Value)).ToArray()));
}
api.Append(" constructor(\r\n");
if (req.Count > 0)
{
api.Append(string.Join("", req.Select(kv => string.Format(" {0}:{1},\r\n", kv.Key, kv.Value)).ToArray()));
}
api.Append(" ){\r\n");
if (req.Count > 0)
{
api.Append(string.Join("", req.Select(kv => string.Format(" this.{0} = {0};\r\n", kv.Key)).ToArray()));
}
api.Append(" }\r\n");
api.Append("\r\n");
api.Append(" public static New(\r\n");
if (req.Count > 0)
{
api.Append(string.Join("", req.Select(kv => string.Format(" {0}:{1},\r\n", kv.Key, kv.Value)).ToArray()));
}
api.AppendFormat(" ):{0}_Request{{\r\n", method.Name);
if (req.Count == 0)
{
api.AppendFormat(" return new {0}_Request;", method.Name);
}
else
{
api.AppendFormat(" return new {0}_Request(\r\n", method.Name);
api.Append(string.Join("", req.Select(kv => string.Format(" {0},\r\n", kv.Key)).ToArray()));
api.Append(" );\r\n");
}
api.Append(" }\r\n");
api.Append(" }\r\n");
api.AppendFormat(" export class {0}Response\r\n",method.Name);
api.Append(" {\r\n");
if (rsp.Count > 0)
{
api.Append(string.Join("",rsp.Select(kv=>string.Format(" {0}:{1};\r\n",kv.Key,kv.Value)).ToArray()));
api.AppendLine();
}
api.Append(" constructor(\r\n");
if (rsp.Count > 0)
{
api.Append(string.Join("", rsp.Select(kv => string.Format(" {0}:{1},\r\n", kv.Key, kv.Value)).ToArray()));
}
api.Append(" ){\r\n");
if (rsp.Count > 0)
{
api.Append(string.Join("", rsp.Select(kv => string.Format(" this.{0} = {0};\r\n", kv.Key)).ToArray()));
}
api.Append(" }\r\n");
api.Append(" }\r\n");
}
api.Append("}");
using (StreamWriter writer = File.CreateText(apiFileName))
{
writer.Write(api);
}
}
static string GetTsType(Type type)
{
Type nullType = Nullable.GetUnderlyingType(type);
if (nullType != null)
{
type = nullType;
}
if (type == typeof(string)
|| type == typeof(long)
|| type == typeof(ulong)
|| type == typeof(double)
|| type == typeof(Guid))
{
return "string";
}
if (type == typeof(int)
|| type == typeof(uint)
|| type == typeof(byte)
|| type == typeof(short)
|| type == typeof(ushort)
|| type == typeof(float)
|| type == typeof(decimal))
{
return "number";
}
if (type == typeof(DateTime))
{
return "Date";
}
if (type == typeof(bool))
{
return "boolean";
}
if (collectionType.IsAssignableFrom(type))
{
if (type.IsGenericType)
{
return string.Format("{0}[]", GetTsType(type.GetGenericArguments()[0]));
}
//ArrayList,Array
return "any[]";
}
if (dictionaryType.IsAssignableFrom(type))
{
return "Map";
}
return "object";
}
npm i -g typescript
tsc --version
tsc --init
tsconfig.json
{
"compilerOptions": {
/* Basic Options */
"target": "es5",
"module": "none", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"lib": ["es2015"], /* Specify library files to be included in the compilation. */
"allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
"sourceMap": false, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./js", /* Redirect output structure to the directory. */
"rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
"removeComments": false, /* Do not emit comments to output. */
"pretty": true,
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": false, /* Enable all strict type-checking options. */
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
"noImplicitThis": false, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
"noImplicitReturns": false, /* Report error when not all code paths in function return a value. */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Advanced Options */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"include": [
"./scripts/soapclient.min.js",
"api.ts"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
tsc --build
调用实例:
webservice.invoke(webservice.MES_PDA_UserLogin,
webservice.MES_PDA_UserLogin_Request.New(
data.field.username,
data.field.password),(rsp)=>{
if(rsp.error)
{
//错误提示
global.message(rsp.error, 2);
}
else
{
if(!rsp.result.MES_PDA_UserLoginResult)
{
global.message(rsp.result.msg, 2);
}
else
{
util.setToken(rsp.result.token);
window.location.replace("main.html");
}
}
});