I only wanted to store some main configuration in a settings file, since the configuration may change any time.
The users of my application will be able to manage some stuff in several environments.
Each environment has its own configuration (Paths to network locations basicly).
I built an struct for each environment, but now we have to add some more environments, so it is helpful to store that configuration outside of the source code.
So, let me give you some code. I built two structs to describe each environment:
public struct env_conf
{
string title;
string path_to_xml;
string path_to_sharepoint;
List<subfolder> subfolders;
//Some more strings
public env_conf(string title, string path_to_xml, string path_to_sharepoint ...)
{
//Constructor which is setting the variables
}
}
public struct subfolder
{
string folder;
bool is_standard;
public env_conf(string folder, bool is_standard)
{
//Constructor which is setting the variables
}
}
And this is how the environment configs are set up:
var finance_conf = new env_conf("MyTitle","MyXMLPath","MySPPath",
new List<subfolder>{new subfolder("MySubFolder",true);new subfolder("MySubFolder2",false)}
);
var sales_conf = new env_conf("MySalesTitle","MySalesXMLPath","MySalesSPPath",
new List<subfolder>{new subfolder("MySalesSubFolder",true);new subfolder("MySalesSubFolder2",false)}
);
This last step - the definition of the config-instances shall now be inside of a settings file.
Saving string and also string[] in settings file was no problem for me so far. But now I have more than that...
More than that, I do NOT have Visual Studio. I work with SharpDevelop, which was very good so far.
Marking my structs as serializable was not helpful. Also, when I manually set the type of the setting to MyNamespace.env_conf, it wont appear in the settings designer - only a "?" appears in the Type-field.
So for now, I don't know how to proceed. Also, all the info I find in the internet doesn't seem to help me. Please help me.
How has my XML settings file to be edited?
How has my source code to be edited?
Greetings!
I would do it by creating serializable classes, then you can deserialize the config file to an instance of your class, and you'll have all the settings.
For example, the classes might look like:
[Serializable]
public class EnvironmentConfig
{
public string Title { get; set; }
public string XmlPath { get; set; }
public string SharepointPath { get; set; }
public List<SubFolder> SubFolders { get; set; }
public override string ToString()
{
return $"{Title}: {XmlPath}, {SharepointPath}, {string.Join(", ", SubFolders.Select(s => s.Folder))}";
}
}
[Serializable]
public class SubFolder
{
public string Folder { get; set; }
public bool IsStandard { get; set; }
}
And then in code, you can create an instance of your class, give it some values, and serialize it to a config file. Later, you can deserialize this file to load any changes your users may have made.
This example creates a default config and displays the values to the console. Then it gives the user a chance to modify the file, and displays the new values.
// Create a default config
var defaultEnvCfg = new EnvironmentConfig
{
Title = "USWE Environment",
XmlPath = #"\\server\share\xmlfiles",
SharepointPath = #"\\server\sites\enterpriseportal\documents",
SubFolders = new List<SubFolder>
{
new SubFolder { Folder = "Folder1", IsStandard = true },
new SubFolder { Folder = "Folder2", IsStandard = false }
}
};
// Display original values:
Console.WriteLine(defaultEnvCfg.ToString());
// Serialize the config to a file
var pathToEnvCfg = #"c:\public\temp\Environment.config";
var serializer = new XmlSerializer(defaultEnvCfg.GetType());
using (var writer = new XmlTextWriter(
pathToEnvCfg, Encoding.UTF8) { Formatting = Formatting.Indented })
{
serializer.Serialize(writer, defaultEnvCfg);
}
// Prompt user to change the file
Console.Write($"Please modify the file then press [Enter] when done: {pathToEnvCfg}");
Console.ReadLine();
// Deserialize the modified file and update our object with the new settings
using (var reader = XmlReader.Create(pathToEnvCfg))
{
defaultEnvCfg = (EnvironmentConfig)serializer.Deserialize(reader);
}
// Display new values:
Console.WriteLine(defaultEnvCfg.ToString());
Console.Write("\nDone!\nPress any key to exit...");
Console.ReadKey();
Related
I am about to create some library that contains all common functions I used in my projects. (Opening File Dialogs, reading spreadsheets, etc..)
And I am planning to use it when I develop some Form application. All my classes are static in that library project.
Here is a example scenario:
I wrote Library.dll and add it to my Form project as reference. I am always using Console.Writeline() to watch what happened in my code. So I did the same in Library.dll.Lets say I have LibraryClass.cs in my Library.dll And when I call a function from that class to Form project I can not see the Console logs inside of that function.
I create another static class at my library called Report.cs. It creates 2 different type of lists. First one is a string list, and using instead of Console.WriteLine(), I am using this string list. I am using Report.WriteLine() function to add strings inside of that string list. It helps me the collect all the logs that I wrote in Form and also in Library.
The second one is a Record object that I created. It contains information like "Code", "Info", "Title" "Reference", "Type" as properties. Type property allows me to define record as an "Error" or "Warning" or just a "Record". If I can catch an error from catch statement or some warning, I am creating an Record object that contains information I mentioned and I am adding it to that Record list in Report.cs. But I am pretty sure there is a more efficient way to do that.
Here is my Record Object:
public class ReportElement
{
public string Info { get; set; }
public string Title { get; set; }
public DateTime Time;
public string Reference { get; set; }
public string Code { get; set; }
public List<string> Targets { get; set; }
public string Log { get; }
public ReportElementType Type { get; set; }
public ReportElement(string code, string info, string title, ReportElementType reportElementType = ReportElementType.kJournal, string reference = null, List<string> targets = null)
{
this.Info = info;
this.Title = title;
this.Time = DateTime.Now;
this.Code = code;
this.Type = reportElementType;
this.Targets = targets;
this.Reference = reference;
this.Log = this.CreateLogString();
Report.WriteLine(this.Log);
}
public enum ReportElementType
{
kError = 0,
kWarning = 1,
kJournal = 2
}
}
And I am collecting that elements in my Report Class inside of a List:
private static List<ReportElement> RecordedReportElements = new List<ReportElement>();
List of logs(Also in report class:
public static List<string> ListLog = new List<string>();
And I am writing strings in that list with that function:
public static void WriteLine(string Text, bool WithTimer = true)
{
try
{
string logString = WithTimer? Text + " | " + GetTimerValue():Text;
ListLog.Add(logString);
Console.WriteLine(logString);
}
catch (Exception e)
{
Console.WriteLine("Can not be saved in List Log : " + Text);
Console.WriteLine(e.Message);
}
}
At the end I can use this library in any other project like this:
Report.WriteLine("MY LOG STRING")
ReportElement NewElement = new ReportElement(Code, Info, Title, ReportElementType, Reference, Targets);
Report.RecordedReportElements.Add(NewELement)
So the summary of the things I need to achieve:
Creating an journal mechanic ( The list that contains all the record object that i created.)
Collect all console logs from the library I used and form application I am developing.
If some error happens at my library, my library also have to be able to terminate my form application.
After termination I want to be able to make some report visible.(as .txt or .xlsx or as an another form)
So at the end anyone has better strategy to do that or some documentation that explains how to catch errors, and create a report after the process done or terminate.
Thanks.
This question already has answers here:
What is App.config in C#.NET? How to use it?
(7 answers)
Closed 3 years ago.
So I want to execute my program with an .exe, and I would like to configure my program without actually write into the code.
I have some yes-no questions in my code, like:
What would you like to zip? File/Directory.
Edit: I don't want to answer these questions in the console application, I would like to answer these before, like before "settings".
And my question is, can I answer these questions without writing into the code, and make this app executable in this way? Are there any programs for it?
Thanks for the answers!
You have 2 approaches you can use depending on your usage preference, the first suggestion is in case you are using your program and you don't set the values too often
You can use app.config file and add relevant values and call them via your code as variables.
You can write to a xml file or json file a small configuration file abd edit it easily and it is also good for clients using your app to change configuration easily via configuration file.
To do this try use xml serialisation and deserialisation object,
I'll add code sample if required.
Edit
to use external configuration you need the next classes:
1. Configuration data object
[Serializable]
public class Configuration : ICloneable
{
public Configuration()
{
a = "a";
b= "b"
}
public string a { get; set; }
public string b { get; set; }
public object Clone()
{
return new Configuration
{
a = a,
b= b
};
}
}
File write and read class
public class ConfigurationHandler
{
// full path should end with ../file.xml
public string DefaultPath = "yourPath";
public ConfigurationHandler(string path = "")
{
if (!File.Exists(DefaultPath))
{
Directory.CreateDirectory(Path.GetDirectoryName(DefaultPath));
FileStream file = File.Create(DefaultPath);
file.Close();
Configuration = new Configuration();
SaveConfigurations(DefaultPath);
}
}
public void SaveConfigurations(string configPath = "")
{
if (string.IsNullOrEmpty(configPath))
configPath = DefaultPath;
var serializer = new XmlSerializer(typeof(Configuration));
using (TextWriter writer = new StreamWriter(configPath))
{
serializer.Serialize(writer, Configuration);
}
}
public Configuration LoadConfigurations(string configPath = "")
{
if (string.IsNullOrEmpty(configPath))
configPath = DefaultPath;
using (Stream reader = new FileStream(configPath, FileMode.Open))
{
// Call the Deserialize method to restore the object's state.
XmlSerializer serializer = new XmlSerializer(typeof(Configuration));
Configuration = (Configuration)serializer.Deserialize(reader);
}
return Configuration;
}
}
to get the configuration instance you can use it from your program:
static void Main(string[] args)
{
var config = new ConfigurationHandler().LoadConfigurations();
//....
}
I'm having an issue where DynamoDB Scan doesn't seem to be mapping results back to the data class correctly. Here's some code:
[DynamoDBTable(TABLE_NAME)]
public class Settings
{
public const string TABLE_NAME = "Settings";
public const string PROPERTY_VALUE_INT = "I";
[DynamoDBHashKey]
public string K { get; set; }
[DynamoDBProperty(PROPERTY_VALUE_INT)]
public int ValueInt { get; set; }
}
I'm able to construct Settings objects and use PutItem to successfully add to the DB entries with fields "K" and "I". However, when I try to then Scan the results, the value of the "I" field does not get mapped into the "ValueInt" field of the Settings object (so the ValueInt field always defaults to 0). If I add an "I" variable to the Settings object, the Scan will map to that field correctly. Why doesn't Scan recognize the DynamoDBProperty Attribute?
Here's the Scan code:
AmazonDynamoDBConfig config = new AmazonDynamoDBConfig()
{
ServiceURL = "http://dynamodb.us-east-2.amazonaws.com"
};
Client = new AmazonDynamoDBClient(config);
Context = new DynamoDBContext(Client);
List<Settings> settings = Context.Scan<Settings>().ToList();
Figured it out. The issue was that I was using the old AWSSDK package instead of the newer AWSSDK.Core and AWSSDK.DynamoDBv2 ones
I'm working on a small WPF app to help me with file organisation. The class I store most of my data in is Project and it contains most of the data the app uses. Therefore, it has a lot of properties which I need to be saved and loaded from a file (around 20, using few as an example)
public DateTime Start { get; set; }
public DateTime End { get; set; }
public Int32 Count { get; set; }
public String Name { get; set; }
public HashSet<String> Files { get; set; }
As far as I know, loading an object can be done in 2 main ways:
I.
Project.cs
public Project Load( String file ) {
Project project = json( file ); //to shorten the question
return project;
}
MainWindow
Project project = new Project();
project = project.Load( file );
II.
Project.cs
public void Load( String file ) {
Project project = json( file );
Start = project.Start;
End = project.End;
Count = project.Count;
Name = project.Name;
Files = project.Files;
}
MainWindow
Project project = new Project();
project.Load( file );
Can I somehow still use void Load() function, but assign the whole object at once?
I tried using this = project;, but it is read-only.
Json .net has a method,
Quick and dirty way to do it using reflection
var project = Json(file); //to shorten the question
foreach (var prop in this.GetType().GetProperties())
{
prop.SetValue(this, prop.GetValue(project));
}
return project;
More performant way using compilation this one is more advanced.
But this looks like somewhat wrong in general when using wpf you should be using some MVVM pattern and the project should be the binding context of your view and you can set the created object from json with out making a copy of the object.
I have a xml file which the path to a particular report folder hardcoded.
eg. C:\git\ProjNew\Proj\Projects_2018\ and C:\git\ProjNew\Proj\Reports\
and xml looks like this:
<SampleFiles>
<SampleFileLocation>C:\git\ProjNew\Proj\Projects_2018\ </SampleFileLocation>
<ReportFileLocation>C:\git\ProjNew\Proj\Reports\</ReportFileLocation>
</SampleFiles>
when someone gets this project from git, they have to manually go to this path and make changes. In the background code, there is a lot of logic happening, is there a way to update it in c#
The c# file looks like this:
[XmlRoot(ElementName = "SampleFiles")]
public class SampleFiles
{
public string SampleFileLocation { get; set; }
public string ReportFileLocation { get; set; }
public SampleFiles()
{
SampleFileLocation = null;
ReportFileLocation = null;
}
}
how do i modify this code in c# so that it doesnt need to be updated by each user .
Thanks,