cemdervis / sharpconfig Goto Github PK
View Code? Open in Web Editor NEWAn easy to use CFG/INI configuration library for .NET.
License: MIT License
An easy to use CFG/INI configuration library for .NET.
License: MIT License
The title is self-explanatory imho.
As an example:
try
{
return Enum.Parse(type, value);
}
catch
{
throw new SettingValueCastException(value, type);
}
To ease logging, I would really like to see the original exception as an inner exception of the SettingValueCastException
😃
Hello.
If we try to save this file with SharpConfig:
[System]
LoggerEnabled=True
LoggerVerbosity=5
MasterServerIP=127.0.0.1
ListenPort=4433
[DEFAULT]
ConnectionType=initiator
UseDataDictionary=Y
ResetOnLogon=Y
ResetOnLogout=Y
ResetOnDisconnect=Y
HeartBtInt=30
ReconnectInterval=30
[SESSION]
BeginString=FIX.4.4
[SESSION]
BeginString=FIX.4.5
We will get mostly empty file as result:
[System]
LoggerEnabled = True
LoggerVerbosity = 5
MasterServerIP = 193.124.113.36
Can you please fix this issue?
Hi,
I'm reading an ini file which contains both comments with a ';' and ';' separated list values like this:
; Pre-section comment
[Section]
setting=value1;value2;value3
I end up with a Section with the correct PreComment, but my setting StringValue is "value1", and the setting Comment is "value2;value3".
Is there a way where I can get the setting value to actually be "value1;value2;value3"? I can workaround to concatenate my stringvalue and comment separated by a ';' but that doesnt feel right at all. So maybe i'm doing something silly, maybe you can add this as a feature? (e.g. RawValue without any comment logic?)
Thanks.
Please change splitting argument in GetFormattedPreComment.
See http://stackoverflow.com/questions/1547476/easiest-way-to-split-a-string-on-newlines-in-net
private string GetFormattedPreComment()
{
string[] lines = PreComment.Split(
new[] { "\r\n", "\n" }, // OLD: new[] { Environment.NewLine },
StringSplitOptions.None
);
return string.Join(
Environment.NewLine,
Array.ConvertAll(lines, s => Configuration.PreferredCommentChar + " " + s)
);
}
Here is a sample bit of code that was a bit puzzling - I have an .ini section [TestRun] with a string array with one of the array values having an apostrophe - when I step through the code (see below .ini entries) the StringValueArray returns a null.
Removing the apostrophe (see 2nd [TestRun] section) then StringValueArray parses properly.
I did not see any exceptions to using StringValueArray and wondered why an apostrophe would create a problem - is this fixable?
`
; fails to parse - StringValueArray returns null but there is an error that is not thrown
[TestRun]
Test = {010|Store A, 020|Store's We Like, 30|Stores We Do Not Like}
; parses fine - Only difference from previous is apostrophe for 020|...
[TestRun]
Test = {010|Store A, 020|Stores We Like, 30|Stores We Do Not Like}
Section test = config["Test"];
string[] _test = test["Test"].StringValueArray;
`
Hi,
v2.1.0 contains following code in Section.cs...
public bool Remove(Setting setting)
{
if (setting == null)
throw new ArgumentNullException("setting");
if (mSettings.Contains(setting))
{
mSettings.Remove(setting);
return true;
}
else
return false;
}
Is it correct to modify as...
public bool Remove(Setting setting)
{
if (setting == null)
throw new ArgumentNullException("setting");
return mSettings.Remove(setting);
}
ref. https://msdn.microsoft.com/en-us/library/cd666k3e(v=vs.110).aspx
and also, if it is true, then similar changes can be applicable else-where in the code base?
My understanding is that is better to keep the ini file to its original design:
http://en.wikipedia.org/wiki/INI_file
Key=value is almost always with no space in my experience and some tools or programs will choke on those spaces.
Also it will be better for existing files to be kept in their original condition as much as possible.
Example:
[section 1]
app=bbb
after Configuration loads it and save's it back it will be:
[section 1]
app = bbb
BTW - I'm enjoying SharpConfig :) good job!
Hi,
Please check following URL...
https://github.com/cemdervis/SharpConfig/wiki/How-to-add-custom-object-string-conversions
In ConvertToString(), '{', '}' is used to delimit string, but in ConvertFromString(), '[', ']' is used to trim/parse it.
Is it type error or my confusion?
2nd issue is, since it is generic class, why 'object' is used as value in input and as return type?
Thanks
I'm trying to install SharpConfig via NuGet using: Install-Package sharpconfig
and it throws this error:
Could not install package 'sharpconfig 1.4.4'. You are trying to install this package into a project that targets '.NETFramework,Version=v3.5,Profile=Unity Subset v3.5', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.
I'm not sure how to fix this.
EDIT: 1.4.3 installed fine so I guess something changed in the latest version?
Sir,
Blank configuration saved to file creates file with size 0 but loading same throws exception.
Technically, any configuration successfully saved must be loadable?
var cfg = new Configuration();
cfg.SaveToFile(@"d:\sample.ini");
cfg = Configuration.LoadFromFile(@"d:\sample.ini");
Hi,
It would be awesome if SharpConfig could actually cope with multiple sections with the same name, instead of ignoring them. Even if config["sectionName"]
just returned the first one, it would be very useful if foreach (Section section in config)
would properly enumerate all of them.
Example configuration:
[server]
ip = 192.168.0.1
[client]
ip = 192.168.0.8
os = Windows
[client]
ip = 192.168.0.9
os = Linux
Hello!
I have an ini file with ' " ' a value of a setting.
But Configuration.ParseSetting(string line) trims every text which is coming afterwards.
Example:
[General]
MySetting=DataSource="MyCustomDataSource;..."
The value of config["General"]["MySetting"] is "DataSource=" and the rest is removed.
Is there any solution for this problem?
Hi,
v2.1.0 contains following code in Section.cs
public Setting this[string name]
{
get
{
var setting = FindSetting(name);
if (setting == null)
{
setting = new Setting(name);
Add(setting);
}
return setting;
}
}
Is it correct to optimize like, because calling Add is not required...
public Setting this[string name]
{
get
{
var setting = FindSetting(name);
if (setting == null)
{
setting = new Setting(name);
mSettings.Add(setting);
}
return setting;
}
}
Thanks
Sir,
Please refer following code snippet, the exception is in LoadConfig().
It used to work in prior versions.
class Program
{
static void Main(string[] args)
{
SaveConfig();
LoadConfig();
}
static void SaveConfig()
{
var cfg = new Configuration();
cfg["Setting"]["Gender"].SetValue<Gender>(Gender.Male);
cfg.SaveToFile("Sample.ini");
}
static void LoadConfig()
{
var cfg = Configuration.LoadFromFile("Sample.ini");
// Exception!
Gender gender = cfg["Setting"]["Gender"].GetValueTyped<Gender>();
}
}
public enum Gender
{
Male,
Female,
}
I've noticed that if I load an ini file with comments, then save all comments are lost.
Is this by design?
Sir,
The issue is related to DateTime field.
While using CreateObject and FromObject methods, if the system date and time settings are different then DateTime field parsing might fail and throw exception.
Is it possible to provide format string or something via field/property attributes?
Thanks
// Sample ini file
[Sample]
Name = Ketan
class Sample
{
public string Name;
public string Address;
}
var sample1 = new Sample();
var cfg = Configuration.LoadFromFile(@"sample.ini");
cfg["Sample"].SetValuesTo(sample1);
Sample sample2 = cfg["Sample"].ToObject<Sample>();
This both yeilds the same result, then what is the difference between these functions?
Thanks
var c= conf["a"]["b"].GetValue<string[]>();
cause an Exception: cannot convert "System.Object[]" to "System.String[]"
Sir,
The android API have concept of SharedPreferences, where you can put application settings. (just like ini), and it have methods like: boolean getBoolean (String key, boolean defValue);
The "defValue" is really useful in case the key/setting does not exist.
I suggest if it can be implemented in SharpConfig...
Like following code will throw exception.
var cfg = new Configuration();
bool isWar = cfg["Rocket"]["Fire"].BoolValue;
Instead it'll be better if we can pass default value, so that it will not be necessary to check if section/setting already exist?
Thanks
If possible, please add following functions...
Section Configuration.Add(string name);
Setting Section.Add(string name);
Setting Section.Add(string name, object value);
Thanks
Hello Cemalettin;
First of all: thank's for your pretty nice helper.
it' working very well.
I tested it a bit a found one problem:
I have an ini with a leading Comment.
It is read from Disk ok, but when i write it to Disk then there is a problem with the Line-ending.
You can only see it in a hex-editor, texteditors correct it automatically.
In the leading Comment is only a linfeed (\n) appended and not a CR\LF (\r\n)
I think the problem is in file "setting.cs" line 528 + 540
return string.Format("{0}\n{1}={2}" should be return string.Format("{0}\r\n{1}={2}",
But i haven't tested it.
May be you can look for?
thanks a lot
best regards
Klaus
Hi,
In .NET API, like File.Delete, If the file to be deleted does not exist, no exception is thrown.
Similarly, Section.Remove() should not throw exception if not exist?
Since, many times it is required to remove sections that might not exist.
But Section.Contains() call is always required for checking.
Thanks
mysql=Data Source=127.0.0.1;Port=3306;userid=root;password=123456;database=test;charset=utf8
when I want to config connectionstring。how can I do?
Please, add new Contains overload:
public bool Contains(string sectionName, string settingName)
{
Section section = FindSection(sectionName);
return section != null && section.Contains(settingName);
}
Hi!
I have this config file:
[Person]
Name = Foo
Age = 234
Gender = Male
In the code there are entities:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Gender Gender { get; set; }
}
public enum Gender
{
Male,
Female
}
Main method:
var config = Configuration.LoadFromFile(@"....config.cfg");
var obj = config["Person"].ToObject<Person>();
When i invoke .ToObject<Person>(); this method throw exception:
SharpConfig.SettingValueCastException:
Failed to convert value 'Male' to type cfg.Gender; no converter for this type is registered. --->
System.NotImplementedException: no converter for this type is registered.
--- End of inner exception stack trace ---
at SharpConfig.Setting.CreateObjectFromString(String value, Type dstType)
at SharpConfig.Setting.GetValue(Type type)
at SharpConfig.Section.SetValuesTo(Object obj)
at SharpConfig.Section.ToObject[T]()
at cfg.Program.Main(String[] args) in C:\....\Program.cs:line 19
If i remove 'Gender' field, all works perfect. Looks like a bug :)
Followed instructions at https://github.com/cemdervis/SharpConfig/wiki/How-to-quickly-get-this-up-and-running-in-Unity
but it throws the following error
Severity Code Description Project File Line Suppression State Error CS8025 Feature 'nameof operator' is not available in C# 4. Please use language version 6 or greater. xmas-kinect.CSharp.Plugins Assets\Plugins\SharpConfig\Section.cs 127 Active
Hi,
var cfg = new Configuration();
var sectionA = cfg["A"];
var section1 = cfg[1];
The 2nd indexer throws exception, why not create section by calling ToString() on numeric value?
Thanks
Hello,
If I want to store in an array an element with spaces, my first guess was to put it within double quotes like this:
Pets = { hamster, cat, mango, "some bird" }
But I found that SharpConfig interprets those quotes as being part of the 4th element. So:
array[3] == "\"some bird\""
Instead of what I expected:
array[3] == "some bird"
This also means I cannot put special characters inside the quoted elements, like for example a comma:
Pets = { hamster, cat, mango, "some,,,bird" }
My use case is: the users of my app will put in that array some filenames they choose to. So they an have weird characters like ,
or }
, so having a way of escaping them seemed reasonably to me.
Hey there!
I recently started to use your library and I'm satifsfied with it so far. There is one question I want to ask.
There is the very useful method for creating objects from configurations. Is there also a method which does the exact opposite?
Greetings
Hi,
I would like to suggest following improvements...
Remove unnecessary using statements
In Setting.cs
public object GetValue(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
if (type.IsArray)
throw new InvalidOperationException("To obtain an array value, use GetValueArray() instead of GetValue().");
if (this.IsArray)
throw new InvalidOperationException("The setting represents an array. Use GetValueArray() to obtain its value.");
return **type.IsArray** ?
GetValueArray(type.GetElementType()) :
CreateObjectFromString(mRawValue, type);
}
It is not required to check this condition.
public T GetValue<T>()
{
var type = typeof(T);
if (type.IsArray)
throw new InvalidOperationException("To obtain an array value, use GetValueArray() instead of GetValue().");
if (this.IsArray)
throw new InvalidOperationException("The setting represents an array. Use GetValueArray() to obtain its value.");
return (T)CreateObjectFromString(mRawValue, type);
}
add check; arrayEndIdx >= arrayStartIdx (true)
// Naive algorithm; assume the number of array element delimiters
// equals the number of elements + 1.
for (int i = 0; i < mRawValue.Length; ++i)
if (mRawValue[i] == Configuration.ArrayElementSeparator)
++arraySize;
i = arrayStartIdx; i < arrayEndIdx; ++i
if (arraySize == 0)
{
// There were no element separators in the array expression.
// That does not mean that there are no elements.
// Check if there is at least something.
// If so, that is the single element of the array.
for (int i = arrayStartIdx + 1; i < arrayEndIdx; ++i)
{
if (mRawValue[i] != ' ')
{
++arraySize;
break;
}
}
}
else **if (arraySize > 0)**
{
// If there were any element separators in the array expression,
// we have to increment the array size, as we assumed
// that the number of element separators equaled the number of elements + 1.
++arraySize;
}
this check is not required.
In private static Setting ParseSetting(string line, int lineNumber) method...
string settingValue = line.Substring(indexOfAssignOp + 1, line.Length - indexOfAssignOp - 1);
line.Substring(indexOfAssignOp + 1) will do
and similar corrections required in some other place too...
Thanks
Hi,
I want char[] as follows, how do I put ini file?
char[] trimChars = { ' ', (char)160, '-', '_', '\'', '\"', '<', '>', '\n', '\r', '\t', ':', '?', (char)30, '\0', '=' };
Thanks
Sir,
For now, we are following this pattern to add/access sections...
Section section = new Section("Sample");
Configuration.Add(section);
It might be helpful to add following support...
Section section = Configuration.Add("Sample");
i.e. Add following API...
Section Configuration.Add(string name);
and similar for Setting class too.
Thanks
Like this
password = x123#
and then SharpConfig give me password x123
Please, change Comment.ToString() to something like below. It's needed to allow using multiline precomments.
public override string ToString()
{
char symbol = Symbol;
return string.Join(
System.Environment.NewLine,
System.Array.ConvertAll(
(Value ?? string.Empty).Split(new string[] { "\r\n", "\n" }, System.StringSplitOptions.None),
s => string.Format("{0} {1}", symbol, s)
)
);
}
Hi, I will try to explain what is my plan, and what is happening
I'm developing two app's that will work together, one simple app, and another with videos and gear vr
on the first app it creates a file, with names, the second app would read this file, and execute the videos and informations
I can see the file, but when I tried to read it, it gives null values, but i can change the values!
like:
on the first app I say: cfg["Person]["Name].SetValue("John");
when I go to the second app, i can't read the name "John", but I can change it to anything else
BUT can't read it either
when I ask to debug the value, it gives me a null value, and when I open the file, shows me the modification
any solution?
public enum GroupItemType
{
Normal,
Tower,
}
static readonly string GROUP_TYPE = "Type";
var groupType = (GroupItemType)Enum.Parse(typeof(GroupItemType), section[GROUP_TYPE].StringValue);
var groupType = section[GROUP_TYPE].GetValue<GroupItemType>();
The last line is causing exception.
And its ArraySize property should be 0 instead of -1.
Currently the method GetValueArray throws a System.OverflowException.
Hi there
you have an amazing tool here it has helped me a great deal in other projects, but now i have a new project that has subsections indicated by double square brackets, how could i improve your code to read a sample like below:
[General] # section1
param = 'config' #section1 parameters and values
[[version]] #section 1 subsection
version_name = 'test_config'
version_string = '1.0p'
[Initialization] #section2
main = 'project'
Section.MapTo() can't overwrite Ini File
Hey there!
another problem I've noticed today:
Section.FromObject()
does not consider arrays, so that it just stores the name of the type and not the array values.string fileName = @"D:\Folder\File.ini";
// Exception if D:\Folder not exist.
cfg.SaveToFile(fileName);
Hey,
Is there any ways to check easily if a section, or a key exist?
Included into this awesome libs, or on my side?
EDIT: Found my issue.
I got an error on:
bool move = conf["Settings"]["move"].BoolValue
saying the instance isn't define to an object.
I fixed it on my side by making a weird workaround, such as:
bool move = Convert.ToBoolean(conf["Settings"]["move"].StringValue);
Hi,
Configuration.ArrayElementSeparator field is not used at some places.
Ref. following code...
mRawValue = string.Format("{{{0}}}", string.Join(",", strings));
Hardcoded ',' is used?
It would be great if we can ignore certain fields or properties by adding an attribute on top of it.
class Person
{
public string Name { get; set; }
public int Age { get; set; }
[Ignore]
public int SomeField;
}
Currently I'm ussing the attribute [IgnoreDataMemberAttribute] available since .NET 3.0. It could be by creating a special attribute for SharpConfig to still support .NET 2.0.
Here the change I made in FromObject function
foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (!prop.CanRead)
{
continue;
}
if (prop.GetCustomAttributes(typeof(IgnoreDataMemberAttribute), true).Length > 0)
{
continue;
}
object propValue = prop.GetValue(obj, null);
Setting setting = new Setting(prop.Name, propValue != null ? propValue.ToString() : "");
section.mSettings.Add(setting);
}
// Repeat for each public field.
foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public))
{
if (field.GetCustomAttributes(typeof(IgnoreDataMemberAttribute), true).Length > 0)
{
continue;
}
object fieldValue = field.GetValue(obj);
Setting setting = new Setting(field.Name, fieldValue != null ? fieldValue.ToString() : "");
section.mSettings.Add(setting);
}
It would be great to add possibility to convert from/to string an arbitrary object type.
As an example it could be done by changing FallbackStringConverter as following.
internal sealed class FallbackStringConverter : ITypeStringConverter
{
public string ConvertToString(object value)
{
try {
return TypeDescriptor.GetConverter(value).ConvertTo(value, typeof(string)) as string;
}
catch
{
//
}
return value.ToString();
}
public object ConvertFromString(string value, Type hint)
{
try
{
return TypeDescriptor.GetConverter(hint).ConvertFrom(value);
}
catch
{
//
}
throw new NotImplementedException();
}
public Type ConvertibleType
{
get { return null; }
}
}
Also method CreateObjectFromString should be changed in following part not to throw an exception.
private static object CreateObjectFromString(string value, Type dstType)
{
................
var converter = Configuration.FindTypeStringConverter(dstType);
if (converter == Configuration.FallbackConverter)
{
// The fallback converter is not able to create arbitrary objects
// from strings, so this means that there is no type converter
// registered for dstType.
throw SettingValueCastException.CreateBecauseConverterMissing(value, dstType);
}
.......................
}
Sir,
Following code maybe invalid/improper, but it adds 'null' in section collection.
var cfg = new Configuration();
cfg["A"] = new Section("B");
Issue related to set indexer, if "A" section not found.
Some validations will be required for such cases?
Configuration.cs -> public Section this[string name]
var section = GetSection(name);
int settingIndex = section != null ? mSections.IndexOf(section) : -1;
if (settingIndex < 0)
{
// A section with that name does not exist yet; add it.
mSections.Add(section); // Must add 'value' ???
}
else
{
// A section with that name exists; overwrite.
mSections[settingIndex] = section;
}
Thanks
The nuget project info still points to the BitBucket repo
Sir,
In Configuration.DateTimeFormat comment, it should be CultureInfo.InvariantCulture.DateTimeFormat rather then CultureInfo.InvariantCulture.NumberFormat?
Is it possible to specify separator in xxxArray(), it looks default is comma.
Something like Configuration.ValidCommentChars?
Incase of string array, if string contains ',' then it might cause issue?
in setting.cs
// Read the last element.
values[i] = ConvertValue(
mRawValue.Substring(elemIndex, mRawValue.Length - elemIndex - 1),
elemType);
while throw exception
change to
// Read the last element.
if (this.ArraySize > 0)
values[i] = ConvertValue(
mRawValue.Substring(elemIndex, mRawValue.Length - elemIndex - 1),
elemType);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.