Use another file constants by dynamic strings C# - c#

I have StoreProcedureConstant.cs file where I've defined constants. I am able to call the constants but can't do it with dynamic strings.
StoreProcedureConstant.cs
public const string testSP = "sp_testingtest";
public const string restSP = "sp_test1";
public const string SP1 = "sp_secondtest";
Service.cs
string[] paramlist = {"testSP","restSP","SP1"};
string[] except = {};
var newparams = paramlist.ToDictionary(key => key, value => value);
foreach (var param in newparams.Values)
{
Data = CommonDBService.ExecuteNonQuery(StoreProcedureConstant.param);
if (Data == false)
{
except.Append(param);
}
}
I have this other file Service.cs from where I am calling the constants from StoreProcedureConstant.cs file.
I am not able to call constants like StoreProcedureConstant.param. So I've converted string array to dictionary but it is still not working.
I am new to c# and I think this is not possible. Please help!!

You need to do something like this:
string[] paramlist = {testSP,restSP,SP1};
But it seems like those names are not available (not in scope). You can possibly address this by adding a using for the StoreProcedureConstant namespace at the top of the Service.cs file, but you may also need to clarify the class name as part of the array.

Related

Pass an object Variable as a String to a Textbox in WPF/C#

I'm creating a practice application to practice using text files as a database.
Take a pipe delineated text file with 14 People Data Entries
Split the text file on the pipes and add each entry to a add each entry (about 150) to a list of the objects.
I've casted list of objects to a string.
Now I want a button click to display that list in a textbox.
Here is the code.
namespace StaffRosterLewis.ViewModel
{
class LoadData
{
public static void LoadRosterData()
{
string mypath = #"J:\zUtilities - Program Files\";
mypath += "StaffRoster - RosterOld.txt";
List<Model.Person> people = new List<Model.Person>();
List<string> lines = File.ReadAllLines(mypath, Encoding.ASCII).ToList();
foreach (var line in lines)
{
string[] entries = line.Split('|');
Model.Person newPerson = new Model.Person
{
LastName = entries[1],
FirstName = entries[2],
Extension = entries[3],
Department = entries[4],
Team = entries[5],
Group = entries[6],
Title = entries[7],
Shift = entries[8],
EmergencyResponder = entries[9],
AEDCPRCert = entries[10],
Languages = entries[11],
Notary = entries[12],
Note = entries[13],
DutyLocation = entries[14]
};
//newPerson.Unknown15 = entries[15];
people.Add(newPerson);
}
people.ToString();
}
}
}
I think the problem is here where the button click happens. I am simply trying to show the content of people above, but I lose the variable "people" no matter how I try to reference it. The above code is public and I made it static so the people variable should be accessible anywhere within the project. (I thought)
private void Button_Show_Click(object sender, RoutedEventArgs e)
{
Button_Show.Content = $"{LoadData.LoadRosterData.people.ToString()}";
}
There are many problems with your code.
You are trying to access a method like a static property here.
Second, you have return type a void, which should be of type string.
Third you should override the ToString method to return the list items as sting in the required format.
You should use Path.Combine to get the path.
If you are planning to make the people as static variable then you have to accept that it’s not thread safe and make sure you reset it whenever it’s necessary else you may face unexpected items in the list.
And your code will throw exception if you have less than 15 |in a line
You don't need to make LoadRosterData static. However, as mentioned by other commenters the method must return a result (in context of your current usage).
Because reading from a file can be resource consuming, you could increase performance when you store the result in a e.g. public property Peoples.
This allows to access the collection without forcing to read the probably unchanged file. Since this would mean to introduce an instance variable, it's recommended to make LoadRosterData an instance member too.
To create a string from the collection you can use the StringBuilder. The below example uses the StringWriter, which allows asynchronous string creation. StringWriter also uses a StringBuilder internally.
You can further improve the code by overriding ToString of the Person type.
To improve the file reading performance you should use the asynchronous API of the StreamReader instead of the synchronous File class. Using StreamReader.ReadLineAsync will also save you an extra loop.
To make file handling and data model creation in particular more convenient, you should consider to make use of serialization.
The recommended text format would be JSON. See Microsoft Docs: How to serialize and deserialize (marshal and unmarshal) JSON in .NET to learn how to do it. Deserializing the JSON file (preferably asynchronously) will automatically produce a collection of Person items without any hassle (this will eliminate the ugly and fragile index based access (to initialize instance properties) as well as making any delimiters like your pipe '|' redundant).
You are accessing the array starting from index '1'. But in computer science, index always starts from '0'. Not sure if you start from index '1' on purpose.
The following code fixes some issues and implements some performance improvements. It also shows how to convert the collection to a string, where each Person item is displayed in it's own line:
PersonDataReader.cs
class PersonDataReader
{
// Consider to use an ImmutableList to prevent modification.
// In the current context, this property could (and probably should) defined private.
public List<Person> Persons { get; }
// If Person is private, 'HasData' has to be defined private too
public bool HasData => this.Persons.Any();
// Constructor
public PersonDataReader() => this.Persons = new List<Person>();
public async Task<string> CreateRosterSummaryAsync()
{
// Use StringWriter to enable asynchronous string creation.
// StringWriter also uses a StringBuilder internally to improve performance.
using (var textWriter = new StringWriter())
{
if (!this.HasData)
{
await LoadRosterDataAsync();
}
// Alternatively use LINQ,
// for example Enuemrable.Select together with Enumerable.Aggregate
// to concatenate the Person.ToString values
foreach (Person person in this.Persons)
{
string personString = person.ToString();
// Write a Person per line
await textWriter.WriteLineAsync(personString);
}
return textWriter.ToString();
}
}
private async Task LoadRosterDataAsync()
{
this.Persons.Clear();
// Use Path.Combine to ensure a valid formatted path (improve robustness)
string sourcePath = Path.Combine(#"J:\zUtilities - Program Files", "StaffRoster - RosterOld.txt");
// Test if the file actually exists to avoid the expensive exception.
// If the file not found exception is desired, remove the File.Exists condition.
if (File.Exists(sourcePath))
{
return;
}
using (var fileReader = new StreamReaeder(sourcePath, Encoding.ASCII))
{
while (!fileReader.EndOfFile)
{
var line = await reader.ReadLineAsync();
string[] personValues = line.Split('|', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
// If you would use serialization, constructing the type explicitly
// can be avoided. A recommended text format to allow easy de-/serialization is the JSON format.
var newPerson = new Model.Person
{
// Check if starting from index '1' is really correct
LastName = personValues[1],
FirstName = personValues[2],
Extension = personValues[3],
Department = personValues[4],
Team = personValues[5],
Group = personValues[6],
Title = personValues[7],
Shift = personValues[8],
EmergencyResponder = personValues[9],
AEDCPRCert = personValues[10],
Languages = personValues[11],
Notary = personValues[12],
Note = personValues[13],
DutyLocation = personValues[14]
};
this.Persons.Add(newPerson);
}
}
}
}
Person.cs
class Person
{
/* Properties of Person */
// Example text representation of a 'People' object
// using string interpolation
public override string ToString()
=> $"Lastname: {this.LastName}; Firstname: {this.FirstName}; Duty location: {this.DutyLocation}";
}
MainWindow.xaml.cs
partial class MainWindow : Window
{
private PersonDataReader PersonDataReader { get; }
public MainWindow()
{
InitializeComponent();
this.PersonDataReader = new PersonDataReader();
}
private async void Button_Show_Click(object sender, RoutedEventArgs e)
{
string personPerLineText = await this.PersonDataReader.CreateRosterSummaryAsync();
// Why did you chose a Button here? It should be
// this.DisplayTextBox.Text = personPerLineText;
this.Button_Show.Content = personPerLineText;
// Consider to display the complete List<Person> in a ListBox.
}
}
Remarks
A ListBox is probably the better choice to display the list of Person. It's more intuitive to implement and would eliminate the need to worry about string representations and creation.
Your method LoadRosterData has a return value void, means nothing. If you would like to return a string value and use it you may do it like this:
//returns a string
public static string MyStringMethod()
{
string str = "My string";
//Specify the return value with the return keyword
return str;
}
Or if you want to return a list:
public static List<string> MyListMethod()
{
List<string> list = new List<string>();
list.Add("one");
list.Add("two");
list.Add("three");
return list;
}
You can't do ToString() with list, but you can refer to the index of a person.
And the useage:
button.Content = $"{MyStringMethod()}"
Or if you want to get person by name you can use IndexOf() method:
List<string> list = new List<string>();
list.Add("one");
list.Add("two");
list.Add("three");
string number = "one";
button.Content = $"list[list.IndexOf(number)]";

Pass Anonymous Type

I am trying to create a utility class where I could pass a list of Anonymous Type (AT) and it would produce a CSV file with the AT's properties as its columns and property values as its respective data.
I have a working code but I feel it could be improved (a lot!). I inherited a class from FileResult and decorate it with my custom implementations. Here's what I have so far:
public class ExportCSVAnonymous : FileResult {
public dynamic List {
set;
get;
}
public char Separator {
set;
get;
}
public ExportCSVAnonymous(dynamic list, string fileDownloadName, char separator = ',') : base("text/csv") {
List = list;
Separator = separator;
FileDownloadName = fileDownloadName;
}
public ExportCSVAnonymous(dynamic list, string fileDownloadName, char separator = ',') : base("text/csv") {
List = list;
Separator = separator;
FileDownloadName = fileDownloadName;
}
protected override void WriteFile(HttpResponseBase response) {
var outputStream = response.OutputStream;
using (var memoryStream = new MemoryStream()) {
WriteList(memoryStream);
outputStream.Write(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
}
}
private void WriteList(Stream stream) {
var streamWriter = new StreamWriter(stream, Encoding.Default);
WriteHeaderLine(streamWriter);
streamWriter.WriteLine();
WriteDataLines(streamWriter);
streamWriter.Flush();
}
//I wish this part could be improved
private void WriteHeaderLine(StreamWriter streamWriter) {
foreach (var line in List) {
foreach (MemberInfo member in line.GetType().GetProperties()) {
WriteValue(streamWriter, member.Name);
}
break;
}
}
private void WriteValue(StreamWriter writer, String value) {
writer.Write("\"");
writer.Write(value.Replace("\"", "\"\""));
writer.Write("\"" + Separator);
}
private void WriteDataLines(StreamWriter streamWriter) {
foreach (var line in List) {
foreach (MemberInfo member in line.GetType().GetProperties()) {
WriteValue(streamWriter, GetPropertyValue(line, member.Name));
}
streamWriter.WriteLine();
}
}
private static string GetPropertyValue(object src, string propName) {
object obj = src.GetType().GetProperty(propName).GetValue(src, null);
return (obj != null) ? obj.ToString() : "";
}
}
I used dynamic as a way to pass my AT inside the class. Is there better way to do this? Lastly, I want to improve the WriteHeaderLine method. Since I am using dynamic type, I cannot cast it successfully to inspect the properties of the AT. What's the best way to do this?
To some extent I feel its a bit overkill, for purposes of writing a CSV, to use an anonymous type (or any type. really) to pass the info purely so you can pass headers too as named properties. I get it, but ask yourself what is the code really doing/what problem are you solving?
You want to write N strings to a file.
That's pretty much it. So you write some simple method:
void WriteCsvLine(path, string[] cells){
File.AppendAllText(path, string.Join(",", cells) + Environment.NewLine);
}
And you call it like:
someContext.Employees.Select(e =>
new [] { e.Name, e.Dept, e.Salary.ToString() }
).ToList().ForEach(x => WriteCsvLine("c:\\...", x) ;
Ah, but we don't want to pass the path every time.. So you upgrade it to be a class, take the path as a constructor arg..
Ah, but we need to escape commas.. So you upgrade it to quote the fields
Ah, but we need to provide some variable delimiter.. So you upgrade it to have another constructor arg
Ah, but we could optimize to write multiple lines at a time.. So you upgrade it to take a List<string[]> or whatever
Ah, but we need to write a header line.. So you just make the first string array you pass to be the headers instead (you can LINQ Concat your data onto a new[]{"Name","Dept","Salary"} or make it a constructor argument..)
So we've need up with something that we maybe use like this:
var x = new CsvWriter("c:\\...", ',', new[]{"EmployeeName","DepartmentName","Salary"});
x.WriteEnumerable(someContext.Employees.Select(e => new [] {
e.Name,
e.Dept,
e.Salary.ToString()
}));
But that's not very cool - surely we can do it cooler.. So you decide you'll pass a KeyValuePair<string, string>[] (or a record or a ValueTuple) where the key is the header and the value is the data.. your calling code bulks up because you're specifying the header name with the data every time..
Ah, but that's still not very cool with all those strings.. So you decide you'll pass an anonymous type where the property name is the header, and the property value is the data..
Your code has some fewer " chars but now the receiving end has become a torturous nightmare of unpacking the property names into being strings so they can be written as a header line.. (and I don't even know if you can easily control the order of columns any more)
Ends up, the problem was simple: "find a way to pass what the header of the column should be", or in other words "pass a string to a method"
..and somehow we went from:
void Print(string what){
Console.WriteLine(what);
}
...
Print("Hello World");
to something like:
using System.Reflection;
static void Print<T>(T what)
{
PropertyInfo[] propertyInfos = what.GetType().GetProperties();
Console.WriteLine(propertyInfos[0].Name.Replace("_", " "));
}
...
Print(new { Hello_World = 0 });
It'll work, but it's a fairly fairly bonkers way of "passing a string to a method" when you think about it..
..and now the boss wants the headers to have percent symbols so I'm off to work out how to get those into property names and also add another bool flag so we can skip writing the header sometimes .. 😀

C# - Remove multiple backslash from JSON data [duplicate]

Given the code:
dynamic foo = new ExpandoObject();
foo.Bar = "something";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
The output is below:
"{\"Bar\":\"something\"}"
When debugging a large json document it is hard to read - using the built in features of Newtonsoft.Json (not regex or hacks that could break things) is there any way to make the output a string with the valie:
{Bar: "something"}
If this happens to you while returning the value from a WebApi method, try returning the object itself, instead of serializing the object and returning the json string. WebApi will serialize objects to json in the response by default; if you return a string, it will escape any double quotes it finds.
So instead of:
public string Get()
{
ExpandoObject foo = new ExpandoObject();
foo.Bar = "something";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
return json;
}
Try:
public ExpandoObject Get()
{
ExpandoObject foo = new ExpandoObject();
foo.Bar = "something";
return foo;
}
Try the JToken.Parse method. I've found that even though when I view JSON objects in the debugger and they are correct, when I go to manipulate them they end up being converted to literals (i.e. backslashes are added). The JToken.Parse method seems to avoid this.
var token = JToken.Parse(text);
So in the case of the original question it would be something like:
dynamic foo = new ExpandoObject();
foo.Bar = "something";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
var token = JToken.Parse(json);
//Do stuff with token -- not json string
In my case specifically the issue was that using JObject.Add(json) would not recognize that my string was json and just insert the entire string as a single property. Once converted into a Jtoken however the JSON was interpreted correctly.
What you see in debugger when looking at the json value is the string value that you should use in a C# file to obtain the same value.
Indeed you could replace
dynamic foo = new ExpandoObject();
foo.Bar = "something";
string json = Newtonsoft.Json.JsonConvert.SerializeObject(foo);
with
string json = "{\"Bar\":\"something\"}";
without changing the program's behaviour.
Thus, to obtain a different value, you should change how JsonConvert works, but JsonConvert conforms to the JSON standard, thus forget it!
If you are not actually serializing ExpandoObject (nor any other sealed class out of your control), you can use the DebuggerDisplayAttribute on the types that you are serializing in json, to define how the object will be shown during debug (in your code, the foo instance).
But a string is a string and VisualStudio is right: double-quotes must be escaped.
Old question but I found this,
In my case, I was looking at the JSON string in a debugger and I found that was adding the escaping.
And when I printed JSON to console, it was without escape characters. Hope it helps.
Instead of using Newstonsoft.Json you should employ the JavaScriptSerializer.Serialize Method:
dynamic foo = new ExpandoObject();
foo.Bar = "something";
var js = new JavaScriptSerializer( );
string json = js.Serialize(foo);
This method produces exactly the output you are looking for. I read about it here.
Its Just simple make the return IHttpActionResult and return the object
public IHttpActionResult Get()
{
ExpandoObject foo = new ExpandoObject();
foo = //query result
return ok(foo)
}
Hey I Just simply write out put to a file
using (System.IO.StreamWriter file =
new System.IO.StreamWriter(#"jsonGonna.txt", true))
{
file.WriteLine(json);
}
now just run the program and you will get without black slash and it good for big programs where you need to save JSON multiple times
Actually it has nothing to do with serializer. It's just because c# don't have single and double quotes concept like Javascipt does. So it can't show string with double quotes without escaping them.
But if you want to put string into html/ cshtml without any escapes you just need to tell compliler that like so:
window.MYVAR = JSON.parse('#Html.Raw(ViewBag.MyStringFromCSharp)');
In case you're getting your data from a controller view method in such a format and finding it difficult to work with in JavaScript. Below is an easy work around:
const CleanUpDifficultJSonData = difficultJSonData => {
const dummyElement = document.createElement('div');
dummyElement.innerHtml = difficultJSonData;
const cleanJSonData = JSON.parse(dummyElement.innerHtml);
return cleanJSonData;
};
const difficultJSonData = "{\"Bar\":\"something\"}";
console.log('cleanJSonData: ',
CleanUpDifficultJSonData(difficultJSonData));
[HttpGet]
public object Get(int id)
{
object result = "";
var db = new dbEntities();
var EO = new System.Dynamic.ExpandoObject() as IDictionary<string, Object>; //needed to return proper JSON without escape slashes
try
{
IEnumerable<usp_GetComplaint_Result> aRow = db.usp_GetComplaint(id);
string DBL_QUOTE = new string(new char[] { '"' });
result = "{";
foreach (usp_GetComplaint_Result oneRow in aRow)
{
System.Reflection.PropertyInfo[] properties = typeof(usp_GetComplaint_Result).GetProperties();
foreach(System.Reflection.PropertyInfo property in properties)
{
var vValue = property.GetValue(oneRow) == null ? "null" : property.GetValue(oneRow);
EO.Add(property.Name,vValue);
}
break;
}
}
catch (Exception ex)
{
result = ex.Message;
EO.Add("Error", result);
}
finally
{
db.Dispose();
}
return Ok(EO);
}

Using getter/setter for splitting a url

I have a url, for example: http://mywebsite.com/another/andanother/test.php I want to be able to split it by / so I can access it in an array like so:
identify[0];
identify[1];
I have a getter and setter like so:
p
How can I achieve what I am looking for?
I get the following error when I try running
Cannot convert string to char
Here's a way to do it, with lazy loading:
private string[] _identify;
public string[] identify
{
get
{
if (_identify == null)
{
_identify = url.Text.Split('/');
}
return _identify;
}
}
Perhaps the existing [Uri class]https://msdn.microsoft.com/en-us/library/system.uri(v=vs.113).aspx) provides what you need.
This:
var uri = new Uri(
"http://scotthannen.org/blog/2017/04/26/dependency-inversion-for-beginners.html");
Console.WriteLine(uri.AbsolutePath);
returns
/blog/2017/04/26/dependency-inversion-for-beginners.html
which you can split by "/".
This:
var uri = new Uri(
"http://scotthannen.org/blog/2017/04/26/dependency-inversion-for-beginners.html");
foreach(var segment in uri.Segments)
{
Console.WriteLine(segment);
}
returns
/
blog/
2017/
04/
26/
dependency-inversion-for-beginners.html
And there are all sorts of other helpful properties and methods for working with urls so you don't have to use all sorts of string methods to parse them.

Get a string representation of a property in C# at run-time

I have seen the reverse of this question quite a few times, but have not seen how to do what I would like.
Suppose I have the following code:
var myNewData = from t in someOtherData
select new
{
fieldName = t.Whatever,
fieldName2 = t.SomeOtherWhatever
};
If I wish to data bind to this class, my column definition would have to include hard-coded strings like "fieldName" and "fieldName2".
Is there any way to call reflection or something else so that I can do something equivelent to the code below (I know the code below is not valid, but am looking for a valid solution).
string columnName = GetPropertyName(myNewData[0].fieldName);
My goal is that if the variable name changes on the anonymous class, a compile-time error would come up until all references were fixed, unlike the current data binding which relies on strings that are not checked until runtime.
Any help would be appreciated.
string columnName = GetPropertyName(() => myNewData[0].fieldName);
// ...
public static string GetPropertyName<T>(Expression<Func<T>> expr)
{
// error checking etc removed for brevity
MemberExpression body = (MemberExpression)expr.Body;
return body.Member.Name;
}
You get your property names like this:
using System.Reflection;
var myNewData = from t in someOtherData
select new
{
fieldName = t.Whatever,
fieldName2 = t.SomeOtherWhatever
};
foreach (PropertyInfo pinfo in myNewData.FirstOrDefault()
.GetType().GetProperties())
{
string name = pinfo.Name;
}
// or if you need all strings in a list just use:
List<string> propertyNames = myNewData.FirstOrDefault()
.GetType().GetProperties().Select(x => x.Name).ToList();

Categories

Resources