See More

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Newtonsoft.Json; using System.Reflection; using Newtonsoft.Json.Linq; namespace AustinHarris.JsonRpc { public class SMD { public string transport { get; set; } public string envelope { get; set; } public string target { get; set; } public bool additonalParameters { get; set; } public SMDAdditionalParameters[] parameters { get; set; } [JsonIgnore] public static List TypeHashes { get; set; } [JsonProperty("types")] public static Dictionary Types { get; set; } [JsonProperty("services")] public Dictionary Services { get; set; } public SMD () { transport = "POST"; envelope = "URL"; target = "/json.rpc"; additonalParameters = false; parameters = new SMDAdditionalParameters[0]; Services = new Dictionary(); Types = new Dictionary(); TypeHashes = new List(); } public void AddService(string method, Dictionary parameters, Dictionary defaultValues) { var newService = new SMDService(transport,"JSON-RPC-2.0",parameters, defaultValues); Services.Add(method,newService); } public static int AddType(JObject jo) { var hash = "t_" + jo.ToString().GetHashCode(); lock (TypeHashes) { var idx = 0; if (TypeHashes.Contains(hash) == false) { TypeHashes.Add(hash); idx = TypeHashes.IndexOf(hash); Types.Add(idx, jo); } } return TypeHashes.IndexOf(hash); } } public class SMDService { ///

/// Defines a service method http://dojotoolkit.org/reference-guide/1.8/dojox/rpc/smd.html /// /// POST, GET, REST, JSONP, TCP/IP /// URL, PATH, JSON, JSON-RPC-1.0, JSON-RPC-1.1, JSON-RPC-2.0 /// /// public SMDService(string transport, string envelope, Dictionary parameters, Dictionary defaultValues ) { // TODO: Complete member initialization this.transport = transport; this.envelope = envelope; this.parameters = new SMDAdditionalParameters[parameters.Count-1]; // last param is return type similar to Func<,> int ctr=0; foreach (var item in parameters) { if (ctr < parameters.Count -1)// never the last one. last one is the return type. { this.parameters[ctr++] = new SMDAdditionalParameters(item.Key, item.Value); } } // create the default values storage for optional parameters. this.defaultValues = new ParameterDefaultValue[defaultValues.Count]; int counter = 0; foreach (var item in defaultValues) { this.defaultValues[counter++] = new ParameterDefaultValue(item.Key, item.Value); } // this is getting the return type from the end of the param list this.returns = new SMDResult(parameters.Values.LastOrDefault()); } public string transport { get; private set; } public string envelope { get; private set; } public SMDResult returns { get; private set; } /// /// This indicates what parameters may be supplied for the service calls. /// A parameters value MUST be an Array. Each value in the parameters Array should describe a parameter /// and follow the JSON Schema property definition. Each of parameters that are defined at the root level /// are inherited by each of service definition's parameters. The parameter definition follows the /// JSON Schema property definition with the additional properties: /// public SMDAdditionalParameters[] parameters { get; private set; } /// /// Stores default values for optional parameters. /// public ParameterDefaultValue[] defaultValues { get; private set; } } public class SMDResult { [JsonProperty("__type")] public int Type { get; private set; } public SMDResult(System.Type type) { Type = SMDAdditionalParameters.GetTypeRecursive(type); } } /// /// Holds default value for parameters. /// public class ParameterDefaultValue { /// /// Name of the parameter. /// public string Name { get; private set; } /// /// Default value for the parameter. /// public object Value { get; private set; } public ParameterDefaultValue(string name, object value) { this.Name = name; this.Value = value; } } public class SMDAdditionalParameters { public SMDAdditionalParameters(string parametername, System.Type type) { Name = parametername; Type = GetTypeRecursive(ObjectType = type); } [JsonIgnore()] public Type ObjectType { get; set; } [JsonProperty("__name")] public string Name { get; set; } [JsonProperty("__type")] public int Type { get; set; } internal static int GetTypeRecursive(Type t) { JObject jo = new JObject(); jo.Add("__name", t.Name.ToLower()); if (isSimpleType(t)) { return SMD.AddType(jo); } var genArgs = t.GetGenericArguments(); PropertyInfo[] properties = t.GetProperties(); FieldInfo[] fields = t.GetFields(); if (genArgs.Length > 0) { var ja = new JArray(); foreach (var item in genArgs) { if (item != t) { var jt = GetTypeRecursive(item); ja.Add(jt); } else { // make a special case where -1 indicates this type ja.Add(-1); } } jo.Add("__genericArguments", ja); } foreach (var item in properties) { if (item.GetAccessors().Where(x => x.IsPublic).Count() > 0) { if (item.PropertyType != t) { var jt = GetTypeRecursive(item.PropertyType); jo.Add(item.Name, jt); } else { // make a special case where -1 indicates this type jo.Add(item.Name, -1); } } } foreach (var item in fields) { if (item.IsPublic) { if (item.FieldType != t) { var jt = GetTypeRecursive(item.FieldType); jo.Add(item.Name, jt); } else { // make a special case where -1 indicates this type jo.Add(item.Name, -1); } } } return SMD.AddType(jo); } internal static bool isSimpleType(Type t) { var name = t.FullName.ToLower(); if (name.Contains("newtonsoft") || name == "system.sbyte" || name == "system.byte" || name == "system.int16" || name == "system.uint16" || name == "system.int32" || name == "system.uint32" || name == "system.int64" || name == "system.uint64" || name == "system.char" || name == "system.single" || name == "system.double" || name == "system.boolean" || name == "system.decimal" || name == "system.float" || name == "system.numeric" || name == "system.money" || name == "system.string" || name == "system.object" || name == "system.type" // || name == "system.datetime" || name == "system.reflection.membertypes") { return true; } return false; } } }