I have this code:
https://dotnetfiddle.net/21G0of
Basically I am curious, about how to cast the object2 - ResponseErrorForSlack to the same format as is the object1 - it should be the same - as can be seen when I serialize both objects to JSON, but when I use JsonResult - the content of the object is different.
Code overview:
public class Program
{
public static void Main()
{
Dictionary<string, string> dict = new();
dict.Add("endOfShiftBlock" ,"End time must be later than start time!");
object object1 = new { response_action = "errors", errors = dict };
ResponseErrorForSlack object2 = new("errors", "endOfShiftBlock", "End time must be later than start time!");
string json1 = JsonConvert.SerializeObject(object1);
string json2 = JsonConvert.SerializeObject(object2);
Console.WriteLine("This is Json from Object1 :" + json1);
Console.WriteLine("This is Json from Object2 :" + json2);
Console.WriteLine();
JsonResult jr1 = new JsonResult(object1);
JsonResult jr2 = new JsonResult(object2);
Console.WriteLine("This is correct: " + jr1.Value);
Console.WriteLine("This is not correct: " + jr2.Value);
}
}
class ResponseErrorForSlack
{
public ResponseErrorForSlack(string responseAction,string blockId = null, string error = null)
{
ResponseAction = responseAction;
if(blockId is not null && error is not null)
{
Errors = new()
{
{ blockId, error }
};
}
}
public ResponseErrorForSlack(string responseAction, Dictionary<string, string> errors)
{
ResponseAction = responseAction;
if (errors is not null)
{
Errors = errors;
}
}
[JsonProperty("response_action")]
public string ResponseAction { get; set; }
[JsonProperty("errors")]
public Dictionary<string, string> Errors { get; set; }
}
What you see in your Console is the output of ToString().
Add the following override to your class ResponseErrorForSlack:
public override string ToString() {
return "Test";
}
and you will see following output:
This is Json from Object1 :{"response_action":"errors","errors":{"endOfShiftBlock":"End time must be later than start time!"}}
This is Json from Object2 :{"response_action":"errors","errors":{"endOfShiftBlock":"End time must be later than start time!"}}
This is correct: { response_action = errors, errors = System.Collections.Generic.Dictionary`2[System.String,System.String] }
This is not correct: Test
A check after your Console.WriteLines, shows up in output as well.
if (jr2.Value.GetType() == typeof(ResponseErrorForSlack))
{
Console.WriteLine("Yeah its correct");
}
Related
I would like to load sparse data in JSON format to get a result with missing data filled in with defaults, but my defaults include predefined instances of an extensible set rather than just fixed fields.
For (arbitrary) example,
Types
class Link
{
public string Addr;
public short Port;
public Link() { Addr = "0.0.0.0"; Port = 80; }
public override string ToString() { return Addr + ":" + Port.ToString(); }
}
class Targets
{
public Link Fixed;
public Dictionary<string, Link> Variable;
public Targets()
{
Fixed = new Link() { Addr = "192.168.0.1" };
Variable = new Dictionary<string, Link>
{
["Common"] = new Link() { Addr = "192.168.0.2" }
};
}
public override string ToString()
{
var result = new System.Text.StringBuilder();
result.Append("Fixed").Append('=').Append(Fixed)
.Append(' ');
foreach (var link in Variable)
{
result.Append(link.Key).Append('=').Append(link.Value)
.Append(' ');
}
return result.ToString();
}
}
Usage
var targets = new Targets();
string json = #"{
'Fixed': { 'Port':12345 },
'Variable': {
'Common': { 'Port':12345 }
}
}";
Newtonsoft.Json.JsonConvert.PopulateObject(json, targets);
Console.WriteLine(targets);
Outputs Fixed=192.168.0.1:12345 Common=0.0.0.0:12345 rather than the desired Fixed=192.168.0.1:12345 Common=192.168.0.2:12345.
This shows that the desired merge logic works for fixed properties, but not for items in a Dictionary despite the fact that the Dictionary will otherwise serialize/deserialize just like a type with fixed properties.
Took me a while to figure this out. Json.NET has a dedicated function for merging two JObjects together. Here's your example modified to use this method:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
namespace ConsoleApp3
{
class Link
{
public string Addr;
public short Port;
public Link() { Addr = "0.0.0.0"; Port = 80; }
public override string ToString() { return Addr + ":" + Port.ToString(); }
}
class Targets
{
public Link Fixed;
public Dictionary<string, Link> Variable;
public Targets()
{
Fixed = new Link() { Addr = "192.168.0.1" };
Variable = new Dictionary<string, Link>
{
["Common"] = new Link() { Addr = "192.168.0.2" },
["Common2"] = new Link() { Addr = "192.168.0.25" }
};
}
public override string ToString()
{
var result = new System.Text.StringBuilder();
result.Append("Fixed").Append('=').Append(Fixed)
.Append(' ');
foreach (var link in Variable)
{
if (link.Key != "Variable")
result.Append(link.Key).Append('=').Append(link.Value)
.Append(' ');
}
return result.ToString();
}
}
class Program
{
static void Main(string[] args)
{
var targets = new Targets();
JObject o1 = JObject.Parse( #"{
'Fixed': { 'Port':12345 },
'Variable': {
'Common': { 'Port':12345 }
}
}");
JObject o2 = JObject.FromObject(targets);
o2.Merge(o1, new JsonMergeSettings
{
// union array values together to avoid duplicates
MergeArrayHandling = MergeArrayHandling.Union
});
string json = o2.ToString();
Console.WriteLine(json);
JsonConvert.PopulateObject(json, targets);
Console.WriteLine(targets);
Console.ReadKey();
}
}
}
The output is:
{
"Fixed": {
"Addr": "192.168.0.1",
"Port": 12345
},
"Variable": {
"Common": {
"Addr": "192.168.0.2",
"Port": 12345
},
"Common2": {
"Addr": "192.168.0.25",
"Port": 80
}
}
}
Fixed=192.168.0.1:12345 Common=192.168.0.2:12345 Common2=192.168.0.25:80
EDIT by OP: Refined into extension methods without extra ToString/deserialization:
static class SerializerExtensions
{
public static T MergeObject<T>(this JsonSerializer serializer, JsonReader json, T target)
{
JObject o1 = JObject.FromObject(target, serializer);
JObject o2 = serializer.Deserialize(json) as JObject;
o1.Merge(o2, new JsonMergeSettings
{ // union array values together to avoid duplicates
MergeArrayHandling = MergeArrayHandling.Union,
// an explicit null removes an existing item
MergeNullValueHandling = MergeNullValueHandling.Merge,
});
serializer.Populate(o1.CreateReader(), target);
return target;
}
public static T MergeObject<T>(this JsonSerializer serializer, JsonReader json, JObject template)
{
JObject o1 = template.DeepClone() as JObject;
JObject o2 = serializer.Deserialize(json) as JObject;
o1.Merge(o2, new JsonMergeSettings
{ // union array values together to avoid duplicates
MergeArrayHandling = MergeArrayHandling.Union,
// an explicit null removes an existing item
MergeNullValueHandling = MergeNullValueHandling.Merge,
});
return serializer.Deserialize<T>(o1.CreateReader());
}
}
I have a webservice that returns json array (JArray) in string format, but I do not understand how to add state value to that operation and get it in the application that consumes the service.
My question is, should I return a json object with a message and inside a json array? Or just an array? hich is more convenient ?
my ws:
public string getList(string strSalary)
{
List<Employee> listJson = null;
JObject jsonResp = "";
JArray array = null;
try
{
listJson = ReportBLL.getInstance.listEmployees(int.Parse(strSalary));
array = JArray.FromObject(listJson);
//set array status ?: ej
//array status = "succes";
}
catch (Exception ex)
{
//set error message
// array status = "error";
//array message = ex.Message or "Not found employees";
}
return JsonConvert.SerializeObject(array);
}
client call (other asp app):
public static List<Employee> listEmployeeClient(string salary)
{
JObject jo = null; //or arrayjson ?
string strData = "";
strData = webService.getList(salary);
jo = JObject.Parse(strData);
//how to evalue status request ?
/* example
if(jo.status == "error") {
throw new Exception(jo.message);
} else {
iterate array inside json object ?
}
*/
}
Is this logic correct ?
You can create a new entity for API Response and use it for all your API responses, You can test it out by the following example.
In server:
Class APIResponse<T>
{
public bool IsError;
public int ErrorCode;
public string ErrorMessage;
public T ReponseData;
}
public string getList(string strSalary)
{
List<Employee> listJson = null;
APIResponse<Employee> responseString = new APIResponse<Employee>();
try
{
listJson = ReportBLL.getInstance.listEmployees(int.Parse(strSalary));
responseString.isError = false;
responseString.data = JArray.FromObject(listJson);
}
catch (Exception ex)
{
responseString.IsError = true;
responseString.ErrorCode = 404; //You can add custom error codes
responseString.ErrorMessage = ex;
}
return JsonConvert.SerializeObject(responseString);
}
In Client:
public static List<Employee> listEmployeeClient(APIResponse<Employee> salary)
{
//You can access the model here
}
There are many options. If you have REST apis you can use the HTTPStatusCodes, for each request, e.g. 200 for OK, 400 bad request, etc.
If you want more fine tuning, you can have a general structure of your response objects, e.g.
responseDto:
status: any code, error or success
message: any error message
data: any expected data
use a Dictionary<string,object> before serializing, and use dynamic to conveniently get the various fields after deserializing. jArray.ToObject<List<Employee>>() will convert JArray object back to the proper type.
Example below:
class Employee
{
public string Name { get; set; }
}
// serializing
var employees = new List<Employee>()
{
new Employee() {Name = "john"},
new Employee() {Name = "alex"},
new Employee() {Name = "susan"},
new Employee() {Name = "bryan"},
};
var dict = new Dictionary<string, object>
{
["employees"] = employees,
["status"] = "error",
["errormessage"] = "Not found employees"
};
var json = JsonConvert.SerializeObject(dict);
// deserializing
dynamic deserialized = JsonConvert.DeserializeObject(json);
string status = deserialized.status;
string errorMessage = deserialized.errormessage;
JArray jArray = deserialized.employees;
List<Employee> deserializedEmployee = jArray.ToObject<List<Employee>>();
I have small program that takes the links from a text file, pass those links to backend system at ImportIO, and save the results to a CSV. However I am seeing following errors after 15,20 min of run. I encounter two exception whichever comes first
1. System.OutOfMemoryException
OR
2. System.NUllReferenceException
Both of these are however I feel my fault somewhere in the code. I am not an expert but I tried to use timer, or closing the files, or even setting objects to null. None worked or even using ArgumentNullException.
I ran the code analysis and it suggested that I should Idispose by this error.
CA1001 Types that own disposable fields should be disposable Implement
IDisposable on 'ImportIO' because it creates members of the following
IDisposable types: 'BlockingCollection>'. Ostock Main.cs 232
My code is as followed, I am not including importIO class it is long. I think solution is easy but I am just not on right path. Could you guys please help?
namespace MinimalCometLibrary
{
class Program
{
private static CountdownEvent countdownLatch;
static void Main(string[] args)
{
string[] lines = File.ReadAllLines(#"C:\Users\James\Desktop\Exper\Input_Links\Stock_links.txt");
for (int i = 0; i < lines.Length; i++)
{
string[] line = lines[i].Split(new string[] { "\t" }, StringSplitOptions.RemoveEmptyEntries);
for (int j = 0; j < line.Length; j++)
{
ImportIO io = new ImportIO("https://query.import.io", Guid.Parse("sdasd-asdasd-NoReal-3easdecb"), "NoReal=");
/* Time Starts
Stopwatch sw = new Stopwatch(); // sw cotructor
sw.Start(); // starts the stopwatch
for (int b = 0; ; b++)
{
if (b % 1000 == 0) // if in 100000th iteration (could be any other large number
// depending on how often you want the time to be checked)
{
sw.Stop(); // stop the time measurement
if (sw.ElapsedMilliseconds > 25) // check if desired period of time has elapsed
{
break; // if more than 5000 milliseconds have passed, stop looping and return
// to the existing code
}
else
{
sw.Start(); // if less than 5000 milliseconds have elapsed, continue looping
// and resume time measurement
}
}
}
//Time Ends
*/
io.Connect();
countdownLatch = new CountdownEvent(1);
// Query for tile SamsClub_Extractor, line[j]
Dictionary<String, Object> query1 = new Dictionary<string, object>();
query1.Add("input", new Dictionary<String, String>() { { "webpage/url", line[j] } });
query1.Add("connectorGuids", new List<String>() { "189f34f3-0f82-4abb-8fbc-f353f35a255a" });
io.DoQuery(query1, HandleQuery);
countdownLatch.Wait();
io.Disconnect();
}
}
Environment.Exit(0);
}
private static void HandleQuery(Query query, Dictionary<String, Object> message)
{
if (message["type"].Equals("MESSAGE"))
{
Console.WriteLine("Got data!");
string JSON = JsonConvert.SerializeObject(message["data"]);
//Deserialize to strongly typed class i.e., RootObject
RootObject obj = JsonConvert.DeserializeObject<RootObject>(JSON);
// handle null reference
if (obj == null) { throw new ArgumentNullException("PleaseKeepRunning"); }
//loop through the list and write to CSV file
foreach (Result resultsItem in obj.results)
{
Console.WriteLine(resultsItem.itemnbr + "-" + resultsItem.price +
"-" + resultsItem.product_name + "_" + obj.pageUrl);
string filePath = #"C:\Users\James\Desktop\Exper\Output_Files\StockPrice_NOW.txt";
//checking if file already exists, if not, create it:
if (!File.Exists(filePath))
{
FileStream fs = new FileStream(filePath, FileMode.CreateNew);
fs.Close();
}
//writing to a file (appending text):
using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write))
{
using (TextWriter tw = new StreamWriter(fs))
tw.WriteLine(resultsItem.itemnbr + "\t" + resultsItem.price + "\t" + resultsItem.product_name + "\t" + resultsItem.misc +
"\t" + resultsItem.qty + "\t" + obj.pageUrl);
fs.Close();
}
//Set object to null
obj = null;
obj.results = null;
}
}
if (query.isFinished) countdownLatch.Signal();
}
}
//root Object
public class Result
{
public double price { get; set; }
public string itemnbr { get; set; }
public string product_name { get; set; }
public string qty { get; set; }
public string misc { get; set; }
}
public class RootObject
{
public List<string> cookies { get; set; }
public List<Result> results { get; set; }
public string pageUrl { get; set; }
public string connectorGuid { get; set; }
public string connectorVersionGuid { get; set; }
public int offset { get; set; }
}
Please excuse my limited knowledge in .net. I am totally new to it. :)
Thanks
---- Edit
I used dispose and using as suggested but I am still facing the error. I am seeing error exception and debugger highlight this code of line in importIO.
new Thread(new ThreadStart(PollQueue)).Start();
I also observe that stock.vshost.exe *32 also keep increasing memory and throw out of memory exception at any time after 70MB or something. I am including the importIO class code
class ImportIO
{
private String host { get; set; }
private int port { get; set; }
private Guid userGuid;
private String apiKey;
private static String messagingChannel = "/messaging";
private String url;
private int msgId = 0;
private String clientId;
private Boolean isConnected;
CookieContainer cookieContainer = new CookieContainer();
Dictionary<Guid, Query> queries = new Dictionary<Guid, Query>();
private BlockingCollection<Dictionary<String, Object>> messageQueue = new BlockingCollection<Dictionary<string, object>>();
public ImportIO(String host = "http://query.import.io", Guid userGuid = default(Guid), String apiKey = null)
{
this.userGuid = userGuid;
this.apiKey = apiKey;
this.url = host + "/query/comet/";
clientId = null;
}
public void Login(String username, String password, String host = "http://api.import.io")
{
Console.WriteLine("Logging in");
String loginParams = "username=" + HttpUtility.UrlEncode(username) + "&password=" + HttpUtility.UrlEncode(password);
String searchUrl = host + "/auth/login";
HttpWebRequest loginRequest = (HttpWebRequest)WebRequest.Create(searchUrl);
loginRequest.Method = "POST";
loginRequest.ContentType = "application/x-www-form-urlencoded";
loginRequest.ContentLength = loginParams.Length;
loginRequest.CookieContainer = cookieContainer;
using (Stream dataStream = loginRequest.GetRequestStream())
{
dataStream.Write(System.Text.UTF8Encoding.UTF8.GetBytes(loginParams), 0, loginParams.Length);
HttpWebResponse loginResponse = (HttpWebResponse)loginRequest.GetResponse();
if (loginResponse.StatusCode != HttpStatusCode.OK)
{
throw new Exception("Could not log in, code:" + loginResponse.StatusCode);
}
else
{
foreach (Cookie cookie in loginResponse.Cookies)
{
if (cookie.Name.Equals("AUTH"))
{
// Login was successful
Console.WriteLine("Login Successful");
}
}
}
}
}
public List<Dictionary<String, Object>> Request(String channel, Dictionary<String, Object> data = null, String path = "", Boolean doThrow = true)
{
Dictionary<String, Object> dataPacket = new Dictionary<String, Object>();
dataPacket.Add("channel", channel);
dataPacket.Add("connectionType", "long-polling");
dataPacket.Add("id", (msgId++).ToString());
if (this.clientId != null)
dataPacket.Add("clientId", this.clientId);
if (data != null)
{
foreach (KeyValuePair<String, Object> entry in data)
{
dataPacket.Add(entry.Key, entry.Value);
}
}
String url = this.url + path;
if (apiKey != null)
{
url += "?_user=" + HttpUtility.UrlEncode(userGuid.ToString()) + "&_apikey=" + HttpUtility.UrlEncode(apiKey);
}
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.GZip;
request.Method = "POST";
request.ContentType = "application/json;charset=UTF-8";
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip");
String dataJson = JsonConvert.SerializeObject(new List<Object>() { dataPacket });
request.ContentLength = dataJson.Length;
request.CookieContainer = cookieContainer;
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(System.Text.UTF8Encoding.UTF8.GetBytes(dataJson), 0, dataJson.Length);
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader responseStream = new StreamReader(response.GetResponseStream()))
{
String responseJson = responseStream.ReadToEnd();
List<Dictionary<String, Object>> responseList = JsonConvert.DeserializeObject<List<Dictionary<String, Object>>>(responseJson);
foreach (Dictionary<String, Object> responseDict in responseList)
{
if (responseDict.ContainsKey("successful") && (bool)responseDict["successful"] != true)
{
if (doThrow)
throw new Exception("Unsucessful request");
}
if (!responseDict["channel"].Equals(messagingChannel)) continue;
if (responseDict.ContainsKey("data"))
{
messageQueue.Add(((Newtonsoft.Json.Linq.JObject)responseDict["data"]).ToObject<Dictionary<String, Object>>());
}
}
return responseList;
}
}
catch (Exception e)
{
Console.WriteLine("Error occurred {0}", e.Message);
return new List<Dictionary<String, Object>>();
}
}
}
public void Handshake()
{
Dictionary<String, Object> handshakeData = new Dictionary<String, Object>();
handshakeData.Add("version", "1.0");
handshakeData.Add("minimumVersion", "0.9");
handshakeData.Add("supportedConnectionTypes", new List<String> { "long-polling" });
handshakeData.Add("advice", new Dictionary<String, int>() { { "timeout", 60000 }, { "interval", 0 } });
List<Dictionary<String, Object>> responseList = Request("/meta/handshake", handshakeData, "handshake");
clientId = (String)responseList[0]["clientId"];
}
public void Connect()
{
if (isConnected)
{
return;
}
Handshake();
Dictionary<String, Object> subscribeData = new Dictionary<string, object>();
subscribeData.Add("subscription", messagingChannel);
Request("/meta/subscribe", subscribeData);
isConnected = true;
new Thread(new ThreadStart(Poll)).Start();
new Thread(new ThreadStart(PollQueue)).Start();
}
public void Disconnect()
{
Request("/meta/disconnect", null, "", true);
isConnected = false;
}
private void Poll()
{
while (isConnected)
{
Request("/meta/connect", null, "connect", false);
}
}
private void PollQueue()
{
while (isConnected)
{
ProcessMessage(messageQueue.Take());
}
}
private void ProcessMessage(Dictionary<String, Object> data)
{
Guid requestId = Guid.Parse((String)data["requestId"]);
Query query = queries[requestId];
query.OnMessage(data);
if (query.isFinished)
{
queries.Remove(requestId);
}
}
public void DoQuery(Dictionary<String, Object> query, QueryHandler queryHandler)
{
Guid requestId = Guid.NewGuid();
queries.Add(requestId, new Query(query, queryHandler));
query.Add("requestId", requestId);
Request("/service/query", new Dictionary<String, Object>() { { "data", query } });
}
}
Try calling Dispose() method because as seen in your error message , it's a memory error because you keep opening files and reading them and then keeping the data there loaded on memory which causes the crash you see after some time
Try this :
if (!File.Exists(filePath))
{
FileStream fs = new FileStream(filePath, FileMode.CreateNew);
fs.Close();
fs.Dispose();
}
Also use the using() { } for the ImportIO class
using(ImportIO myIO = new ImportIO) { }
I can't say if your exceptions are related to it or not without seeing complete code, but the warning is about an issue "in" ImportIO, not in the code that's calling it (it's complaining that the ImportIO class does not implement IDisposable, not that you do something wrong with it)
Since you edited with the class : just implement IDisposable on your ImportIO class, here's a link on how to properly implement IDisposable : Implementing IDisposable correctly
Make sure to dispose of the BlockingCollection in the dispose of your ImportIO.
Then wrap your ImportIO in a using and the warning should go away. I'd be surprised if that alone caused those exceptions however but this is the way to fix your warning.
I'm using JSON for data interchange. And I'm using JSON.NET framework.
I have the class:
public class CarEntity
{
public string Model { get; set; }
public int Year { get; set; }
public int Price { get; set; }
}
And I have following code:
public void Test()
{
var jsonString =
#"{
""Model"": ""Dodge Caliber"",
""Year"": 2011,
""Price"": 15000,
""Mileage"": 35000
}";
var parsed = (CarEntity)JsonConvert.DeserializeObject(jsonString, typeof(CarEntity));
}
Since there are no "Mileage" field in CarEntity class I need log warning about it:
Unknown field: Mileage=35000
Is there some way to do it?
It is little tricky but you can. Change your code to:
var parsed = (CarEntity)JsonConvert.DeserializeObject(jsonString, typeof(CarEntity), new JsonSerializerSettings()
{
MissingMemberHandling = MissingMemberHandling.Error,
Error = ErrorHandler
});
And add:
private static void ErrorHandler(object x, ErrorEventArgs error)
{
Console.WriteLine(error.ErrorContext.Error);
error.ErrorContext.Handled = true;
}
You should probably do more with the last line, because now every error will not throw an exception.
UPDATE
Decompiled code form invoking exception in Json.NET:
if (this.TraceWriter != null && this.TraceWriter.LevelFilter >= TraceLevel.Verbose)
this.TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, StringUtils.FormatWith("Could not find member '{0}' on {1}", (IFormatProvider) CultureInfo.InvariantCulture, (object) propertyName, (object) contract.UnderlyingType)), (Exception) null);
if (this.Serializer.MissingMemberHandling == MissingMemberHandling.Error)
throw JsonSerializationException.Create(reader, StringUtils.FormatWith("Could not find member '{0}' on object of type '{1}'", (IFormatProvider) CultureInfo.InvariantCulture, (object) propertyName, (object) contract.UnderlyingType.Name));
reader.Skip();
For an application I'm working on I'm trying to display a template that will show what the parameters for a (runtime-determined) method look like. The test case I'm working on should show "PERSON = (FIRST = first; LAST = last);", where the parameter named Person has type Name, and Name has two properties, First and Last. The following code instead shows "PERSON = ();".
GetNestedTypes is not returning anything, any ideas why?
public static string GetParameterTemplate(MethodInfo method)
{
StringBuilder output = new StringBuilder();
foreach (ParameterInfo pi in method.GetParameters())
{
output.Append(parameterTemplateHelper(pi.Name, pi.ParameterType));
}
return output.ToString();
}
private static string parameterTemplateHelper(string pName, Type pType)
{
string key = pName.ToUpper();
string value = "";
if (pType.IsPrimitive)
{
// it's a primitive
value = pName.ToLower();
}
else if (pType.IsArray)
{
if (pType.GetElementType().IsPrimitive)
{
// array of primitives
value = String.Format("{0}1, {0}2;", pName.ToLower());
}
else
{
// array of objects
StringBuilder sb = new StringBuilder();
foreach (Type t in pType.GetElementType().GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic))
{
sb.Append(parameterTemplateHelper(t.Name, t));
}
value = String.Format("({0}), ({0});", sb);
}
}
else
{
// object
StringBuilder sb = new StringBuilder();
Type[] junk = pType.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
foreach (Type t in pType.GetNestedTypes())
{
sb.Append(parameterTemplateHelper(t.Name, t));
}
value = String.Format("({0});", sb.ToString());
}
string output = key + " = " + value.ToString();
return output;
}
Your code is looking for nested types - that is, other types declared within Person. That's not at all the same as looking for properties within Person.
Here's a class with nested types:
public class Name
{
public class Nested1 {}
public class Nested2 {}
}
Here's a class with properties:
public class Name
{
public string Name { get; set; }
public string Name { get; set; }
}
My guess is that your situation is much more like the second one than the first... so use Type.GetProperties instead of Type.GetNestedTypes.