Accessing a Json array as string array - c#

I have this code which reads from my json file an array of words
public static string[] GetProfanity()
{
var json = string.Empty;
using (var fs = File.OpenRead("profanity.json"))
using (var sr = new StreamReader(fs, new UTF8Encoding(false)))
json = sr.ReadToEnd();
var profanityJson = JsonConvert.DeserializeObject<ProfanityJson>(json);
return profanityJson.badwords;
}
This is the json
{
"badwords" : ["bad", "stupid"]
}
And i try to access this here
public static bool ProfanityCheck(string inputString)
{
string[] badWords = GetProfanity();
string checkString = inputString.ToLower();
if (badWords.Any(checkString.Contains))
return true;
return false;
}
As requested I access the ProfanityCheck method here
[Command("echo")]
[Description("says whatever the user gives")]
public async Task Echo(CommandContext ctx, [RemainingText] string echoText)
{
bool hasProfanity = ProfanityFilter.ProfanityCheck(echoText);
if(hasProfanity)
{
var errMsg = ProfanityFilter.ErrorMessage();
var errSent = await ctx.Channel.SendMessageAsync(embed: errMsg).ConfigureAwait(false);
Thread.Sleep(3000);
await ctx.Channel.DeleteMessageAsync(errSent).ConfigureAwait(false);
await ctx.Channel.DeleteMessageAsync(ctx.Message).ConfigureAwait(false);
return;
}
await ctx.Channel.SendMessageAsync(echoText).ConfigureAwait(false);
}
and the struct I Deserialize it as
public struct ProfanityJson
{
[JsonProperty("badwords")]
public string[] badwords { get; private set; }
}
but when i attempt to search for this any bad words in a string I pass, nothing happens, no errors in the console, no output otherwise. I have it set up so that it sends me an error message when profanity is found, but in its current state it does nothing when profanity is passed

Your code seems to be correct... I would write the GetProfanity() in another way (and I wouldn't surely reread it every time a word is passed to to ProfanityCheck) but this is tangential to your problem. I've written a minimum testable example:
public class ProfanityJson
{
public string[] badwords { get; set; }
}
public static class ProfanityChecker
{
public static string[] GetProfanity()
{
var json = string.Empty;
using (var fs = File.OpenRead("profanity.json"))
using (var sr = new StreamReader(fs, new UTF8Encoding(false)))
json = sr.ReadToEnd();
var profanityJson = JsonConvert.DeserializeObject<ProfanityJson>(json);
return profanityJson.badwords;
}
public static string[] GetProfanity2()
{
using (var sr = new StreamReader("profanity.json"))
using (var jtr = new JsonTextReader(sr))
{
var ser = new JsonSerializer();
var profanityJson = ser.Deserialize<ProfanityJson>(jtr);
return profanityJson.badwords;
}
}
public static bool ProfanityCheck(string inputString)
{
string[] badWords = GetProfanity2();
Trace.WriteLine($"Loaded {badWords.Length} bad words");
string checkString = inputString.ToLower();
if (badWords.Any(checkString.Contains))
return true;
return false;
}
}
static void Main(string[] args)
{
Console.WriteLine(ProfanityChecker.ProfanityCheck("badder"));
}
So the only idea I have is that you are using a "stale" version of profanity.json. I've added a little loggin in the ProfanityCheck() method. It will go to the Output pane in Visual Studio.

(Would be a mess as a comment)
You could have your class like this:
public class ProfanityJson
{
[JsonProperty("badwords")]
public string[] Badwords { get; set; }
}
Is it like so? Json is case sensitive.

Related

How to display deserialized Json result on Winform tabPage in C#

Please I need your help here, I could not write the logic to display the deserialized JSON result on tabPage in Winforms C#
public Form1()
{
var path = #"C:\Users\elitebook\source\repos\ExamCBT\question.json";
string jsonFile = File.ReadAllText(path);
Question q = JsonConvert.DeserializeObject<Question>(jsonFile);
InitializeComponent();
}
jsonFile = tabPage2.ToString();
You can use these methods for serializing & deserializing JSON. Just download the Newtonsoft.Json NuGet package.
static class FileHelper
{
public static void JsonSerialize(object obj, string fileName)
{
using (var sw = new System.IO.StreamWriter($"{fileName}.json"))
using (var jw = new Newtonsoft.Json.JsonTextWriter(sw))
{
var serializer = new Newtonsoft.Json.JsonSerializer();
jw.Formatting = Newtonsoft.Json.Formatting.Indented;
serializer.Serialize(jw, obj);
}
}
public static void JsonDeserialize(out string/*object, List<>, or something else*/ obj, string fileName)
{
using (var sr = new System.IO.StreamReader($"{fileName}.json"))
{
using (var jr = new Newtonsoft.Json.JsonTextReader(sr))
{
var serializer = new Newtonsoft.Json.JsonSerializer();
try
{
obj = serializer.Deserialize<string /*object, List<>, or something else...*/>(jr);
}
catch
{
obj = null;
}
}
}
}
}
And you can add JSON data to TabPage like this.
Label label = new Label(); // label can be textbox, button or something else...
FileHelper.JsonDeserialize(out string /*object, List<>, or something else...*/ data, "test");
label.Text = data //data type is string
tabPage1.Controls.Add(label);

Merge Sparse Data into Dictionary using Json.NET PopulateObject

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());
}
}

Mock method in Parallel.ForEach always returns null

I have the following code:
public int LoadFilesAndSaveInDatabase(string filesPath)
{
var calls = new ConcurrentStack<GdsCallDto>();
var filesInDirectory = this._directoryProxy.GetFiles(filesPath);
if (filesInDirectory.Any())
{
Parallel.ForEach(filesInDirectory, file =>
{
var lines = this._fileProxy.ReadAllLines(file, Encoding.Unicode);
if (lines.Any())
{
// Reads the file and setup a new DTO.
var deserializedCall = this._fileManager.DeserializeFileContent(lines, Path.GetFileName(file));
// Insert the DTO in the database.
this._gdsCallsData.InsertOrUpdateGdsCall(deserializedCall);
// We keep track of the dto to count the number of restored items.
calls.Push(deserializedCall);
}
});
}
return calls.Count;
}
And I have the following unit test:
[TestMethod]
public void ShouldLoadFilesAndSaveInDatabase()
{
// Arrange
var path = RandomGenerator.GetRandomString(56);
var encoding = Encoding.Unicode;
var fileNameEnvironment = RandomGenerator.GetRandomString();
var fileNameModule = RandomGenerator.GetRandomString();
var fileNameRecordLocator = RandomGenerator.GetRandomString(6);
var fileNameTimestamp = RandomGenerator.GetRandomDateTime().ToString("O").Replace(':', 'o');
// We simulate the presence of 4 files.
var files = new List<string>
{
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255)
}.ToArray();
var expectedResult = 4;
this._directoryProxy.Expect(d => d.GetFiles(path))
.Return(files);
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length);
// Act
var result = this._databaseReloadManager.LoadFilesAndSaveInDatabase(path);
// Assert
Assert.AreEqual(result, expectedResult);
this._directoryProxy.AssertWasCalled(d => d.GetFiles(path));
this._fileProxy.AssertWasCalled(f => f.ReadAllLines(path, Encoding.Unicode));
}
The problem is on the following line:
var lines = this._fileProxy.ReadAllLines(file, Encoding.Unicode);
Even though I set an expectation and a return value, when I run the unit test, it always returns null.
I am using Rhino.Mocks, it works perfectly fine elsewhere but not there.
I had a look at some discussions here but none of them helped. Can it be due to the use of Parallel.ForEach? Is there a way of doing such a mock?
If you need any other info, please let me know.
I don't think there is a problem with the Parallelization. It seems your problem is related to the proxy instance setup with Rhino Mock.
Ensure what you pass into the parameters of the ReadAllLines are the same as you call them when it run through the production code.
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length);
For instance if you setup on different path and the value of that path diefferent when test executes you may see NULL in return. But again hard to tell without seeing the full setup/constructor in the code. Also check the random generators see what has been used in each time.
The below is I sort of put together and working for me.
Working means I don't get NULL for:
var lines = this._fileProxy.ReadAllLines(file, Encoding.Unicode);
//some dummy code so I can compile
public interface IProxyDir
{
IEnumerable<string> GetFiles(string path);
}
public class GdsCallDto
{
}
public class Proxy : IProxyDir
{
public IEnumerable<string> GetFiles(string path)
{
throw new NotImplementedException();
}
}
public interface IFileDir
{
IEnumerable<string> ReadAllLines(string path, Encoding encoding);
}
public class FileProxy : IFileDir
{
public IEnumerable<string> ReadAllLines(string path, Encoding encoding)
{
throw new NotImplementedException();
}
}
public interface IFileMgr
{
string DeserializeFileContent(IEnumerable<string> lines, string content);
}
public class FileMgr : IFileMgr
{
public string DeserializeFileContent(IEnumerable<string> lines, string content)
{
throw new NotImplementedException();
}
}
//system under test
public class Sut
{
private IProxyDir _directoryProxy;
private IFileDir _fileProxy;
private IFileMgr _fileManager;
public Sut(IProxyDir proxyDir, IFileDir fileProxy, IFileMgr mgr)
{
_fileManager = mgr;
_directoryProxy = proxyDir;
_fileProxy = fileProxy;
}
public int LoadFilesAndSaveInDatabase(string filesPath)
{
var calls = new ConcurrentStack<GdsCallDto>();
var filesInDirectory = this._directoryProxy.GetFiles(filesPath);
if (filesInDirectory.Any())
{
Parallel.ForEach(filesInDirectory, file =>
{
var lines = this._fileProxy.ReadAllLines("ssss", Encoding.Unicode);
if (lines.Any())
{
// Reads the file and setup a new DTO.
var deserializedCall = this._fileManager.DeserializeFileContent(lines, Path.GetFileName("file"));
// Insert the DTO in the database.
//this._gdsCallsData.InsertOrUpdateGdsCall(deserializedCall);
// We keep track of the dto to count the number of restored items.
//calls.Push(deserializedCall);
}
});
}
return 1;
}
}
Sample Unit Test
[TestClass]
public class UnitTest1
{
private IProxyDir _directoryProxy;
private IFileDir _fileProxy;
private IFileMgr _fileMgr;
private Sut _sut;
public UnitTest1()
{
_directoryProxy = MockRepository.GenerateMock<IProxyDir>();
_fileProxy = MockRepository.GenerateMock<IFileDir>();
_fileMgr = MockRepository.GenerateMock<IFileMgr>();
}
[TestMethod]
public void ShouldLoadFilesAndSaveInDatabase()
{
// Arrange
var path = RandomGenerator.GetRandomString(56);
var encoding = Encoding.Unicode;
var fileNameEnvironment = RandomGenerator.GetRandomString(5);
var fileNameModule = RandomGenerator.GetRandomString(5);
var fileNameRecordLocator = RandomGenerator.GetRandomString(6);
var fileNameTimestamp = RandomGenerator.GetRandomDateTime().ToString("O").Replace(':', 'o');
// We simulate the presence of 4 files.
var files = new List<string>
{
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255),
RandomGenerator.GetRandomString(255)
}.ToArray();
var expectedResult = 4;
this._directoryProxy.Expect(d => d.GetFiles(path))
.Return(files);
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length);
_sut = new Sut(_directoryProxy, _fileProxy, _fileMgr);
// Act
var result = this._sut.LoadFilesAndSaveInDatabase(path);
// Assert
Assert.AreEqual(result, expectedResult);
this._directoryProxy.AssertWasCalled(d => d.GetFiles(path));
this._fileProxy.AssertWasCalled(f => f.ReadAllLines(path, Encoding.Unicode));
}
}
internal class RandomGenerator
{
public static string GetRandomString(int number)
{
return "ssss";
}
public static DateTime GetRandomDateTime()
{
return new DateTime();
}
}
I could get rid of this issue, probably caused by the use of random values. I am now calling the method IgnoreArguments() on my expectation:
this._fileProxy.Expect(f => f.ReadAllLines(path, encoding))
.Return(files).Repeat.Times(files.Length).IgnoreArguments();
It does the trick (i.e. the unit test is running successfully), but I do not know if it is very elegant.

Memory Exception; NullReference; CA1001 implement IDisposable

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.

how do I set the current class to the return types results

I have this class:
using System.IO;
using System.Xml.Serialization;
namespace ssscc.Settings
{
public class AppSettings
{
private string _companyName;
public string CompanyName
{
set { _companyName = value; }
get
{
if (string.IsNullOrWhiteSpace(_companyName))
{
LoadSettings();
}
return _companyName;
}
}
private string _companyPhone;
public string CompanyPhone
{
set
{
_companyPhone = value;
}
get
{
if (string.IsNullOrWhiteSpace(_companyPhone))
{
LoadSettings();
}
return _companyPhone;
}
}
private string GetSettingsFile()
{
var exePath = System.Windows.Forms.Application.StartupPath;
var sharedDirectory = Path.Combine(exePath, "shared");
var settingsDirectory = Path.Combine(sharedDirectory, "settings");
var settingsFile = Path.Combine(settingsDirectory, "ssscc.xml");
if (!Directory.Exists(sharedDirectory))
{
Directory.CreateDirectory(sharedDirectory);
}
if (!Directory.Exists(settingsDirectory))
{
Directory.CreateDirectory(settingsDirectory);
}
return settingsFile;
}
internal void SaveSettings(AppSettings settings)
{
var serializer = new XmlSerializer(typeof(AppSettings));
using (var stream = File.OpenWrite(GetSettingsFile()))
{
serializer.Serialize((Stream) stream, (object) settings);
}
}
internal void LoadSettings()
{
if (!File.Exists(GetSettingsFile()))
{
return;
}
var serializer = new XmlSerializer(typeof(AppSettings));
using (var stream = File.OpenRead(GetSettingsFile()))
{
var appsetting = (AppSettings) serializer.Deserialize(stream);
CompanyPhone = appsetting.CompanyPhone;
CompanyName = appsetting.CompanyName;
}
}
}
}
My question is about this code:
var appsetting = (AppSettings) serializer.Deserialize(stream);
CompanyPhone = appsetting.CompanyPhone;
CompanyName = appsetting.CompanyName;
I am pretty sure there is a way to return the appsettings directly to the class that contains the method so I do not have to loop through each property such as this:
CompanyPhone = appsetting.CompanyPhone;
CompanyName = appsetting.CompanyName;
Can I assign the properties directly without having to maintain this code?
You are getting a new instance of AppSettings while deserializing from file. You may use it, can't you? Try to replace LoadSettings with a static factory method like this:
internal static AppSettings GetInstance()
{
if (!File.Exists(GetSettingsFile()))
return null;
var serializer = new XmlSerializer(typeof(AppSettings));
using (var stream = File.OpenRead(GetSettingsFile()))
return (AppSettings)serializer.Deserialize(stream);
}
while to save your settings, you have no need to pass the settings object as an argument. I guess the following code should do the job:
internal void SaveSettings()
{
var serializer = new XmlSerializer(typeof(AppSettings));
using (var stream = File.OpenWrite(GetSettingsFile()))
serializer.Serialize((Stream)stream, this);
}
Use the factory GetInstance method to initialize settings (well, as an example):
var s = AppSettings.GetInstance();
if (s == null)
{
s = new AppSettings
{
CompanyName = "MyCompany",
CompanyPhone = "######"
};
s.SaveSettings();
}
P.S.: if properties getters and setters have no additional logic (LoadSettings method no longer exists), you could use auto-properties:
public string CompanyName { get; set; }
public string CompanyPhone { get; set; }
and GetSettingsFile may be declared as static, as it does not operate any of the instance class members:
private static string GetSettingsFile()
{
//...
return settingsFile;
}
Do you really need to have lazy-loading in here, if not, make your methods explicitly:
public class AppSettings
{
private static readonly XmlSerializer Serializer
= new XmlSerializer(typeof(AppSettings));
public string CompanyName { get; set; }
public string CompanyPhone { set; get; }
private static string GetSettingsFile()
{
return null;
}
public static void SaveSettings(AppSettings settings)
{
using (var stream = File.OpenWrite(GetSettingsFile()))
Serializer.Serialize(stream, settings);
}
internal static AppSettings LoadSettings()
{
if (!File.Exists(GetSettingsFile()))
return null;
object appsetting = null;
using (var stream = File.OpenRead(GetSettingsFile()))
appsetting = Serializer.Deserialize(stream);
return appsetting as AppSettings;
}
}
Do you can use:
var setting = AppSettings.LoadSettings();
and:
AppSettings.SaveSettings(setting);
Please note in here, creating XmlSerializer everytime will get the memory leak,
The XmlSerializer constructor will generate a pair of classes derived from XmlSerializationReader and XmlSerializationWriter by analyzing the Person class using reflection. It will create temporary C# files, compile the resulting files into a temporary assembly, and finally load that assembly into the process. Code gen like this is also relatively expensive. So the XmlSerializer caches the temporary assemblies on a per-type basis. This means that the next time an XmlSerializer for the Person class is created, the cached assembly is used rather than a new one generated.
Therefore, you should keep XmlSerializer as static.

Categories

Resources