Retrieve values from a config file into a class, in C#? - c#-3.0

Using C#. how would one get values from a config file into a class? I guess you can pass a key and it will get the value based on that.
I know you can use
string value = ConfigurationManager.AppSettings["test"];
But I thought there might be a better way, maybe using it in a class?
Is this OK?
public static string GetKey(string value)
{
get
{
return ConfigurationSettingAppSetting[value];
}
}
and to use it I use
GetKey("test");
Is this good or good pratice using it as a static?
thanks

I prefer not to use strings to get values out of the configuration. Instead I create
public static class Config
{
public static string Test
{
get { return ConfigurationManager.AppSettings["Test"]; }
}
}
also allowing for strong typing
public static class Config
{
public static int ApplicationId
{
get { return int.Parse(ConfigurationManager.AppSettings["ApplicationId"]); }
}
}
This creates a simple abstraction without going all out and creating configuration sections.

Related

Custom annotation processing while coding

The purpose of the project I'm working on is to handle annotation at compile time, it is not focused on what exactly I'm developing.
I took a simple subject for this and I'm writing a custom collection that will store elements and provide methods to manage them.
What I wanna do is to create an annotation #Contains, for example, to generate itemsContains method that could be processed while coding (instead of writing code manually).
public class Array {
private List<String> items;
public Array() {
items = Arrays.asList("abc", "def", "xyz");
}
public boolean itemsContains(String expected) {
return items.contains(expected);
}
}
Generally, I want my class to look something like:
public class Array {
#Contains
private List<String> items;
public Array() {
items = Arrays.asList("abc", "def", "111");
}
}
The important thing I want to reach is to have itemsContains method show up once the annotation is applied to a field. This is how it should look like:
expected result
Alternate existing examples are Lombok's #Getter/#Setter.
So what functionality or configurations should I implement to get the expected result?
Would be grateful for some real implementations or guides how to perform it step by step.
Annotation processing does not change the source file yet it generates a new file,
Lombok on the other hand does a trick to modify the source file itself, meaning that you need to call the generated class somewhere in your code.
One way to do this is to generate a class that extends the main class
#Generated
public class ArrayProxy extends Array {
public boolean itemsContains(String expected) {
return items.contains(expected);
}
}
and in your main class you need to do two things:
first you need to make items protected
you can add factory method to actually create the generated class
public class Array {
#Contains
protected List<String> items;
public static ArrayProxy create(){
return new ArrayProxy();
}
private Array() {
items = Arrays.asList("abc", "def", "111");
}
}
And of course you need to use it like this
ArrayProxy array = Array.create();
array.itemsContains("expected");

Represent a single-rowed table in EF?

I have a configuration table in my database and it contains exactly one row.
ConfirmedScheduleColor | OverlappedScheduleColor | ColN
Currently, I'm retrieving the configuration like this:
var db = new SchedulingDbContext();
var config = db.Configurations.FirstOrDefault();
It's currently working fine and I can access my configurations and all. The thing is, the code looks awkward since I'm accessing the Configurations DbSet as if it contains many records (FirstOrDefault()); although actually, it contains only one record. I want to access my configurations like I'm accessing a static object. How to do that in EF?
You could simply add a property to your DbContext that returns Configurations.FirstOrDefault() and privatize the DbSet:
public class SchedulingDbContext : DbContext
{
private DbSet<Configuration> Configurations { get; set; }
public Configuration Configuration
{
get
{
return Configurations.FirstOrDefault();
}
}
}
I have a class in my project that has static methods to retrieve config settings. I use the ConfigurationManager rather than the database, but you could adapt it to get the setting from wherever you are storing the value.
In my example I have written a GetFromDb method for you that takes a key as parameter but that is because if I was storing my config settings in the database I wouldn't want to add a column every time I needed a new config setting. I would have a table with Key/Value columns. If you are wedded to the single row table then you might want to do without such a method.
public class Config
{
private _ConfirmedScheduleColor;
public static string ConfirmedScheduleColor
{
get
{
if(_ConfirmedScheduleColor == null)
_ConfirmedScheduleColor = GetFromDb("ConfirmedScheduleColor");
return _ConfirmedScheduleColor;
}
}
public static string OverlappedScheduleColor
{
get { return GetValue("OverlappedScheduleColor", "Pink"); }
}
public static int ColN
{
get { return GetValue("ColN", 2); }
}
private static string GetFromDb(string key)
{
if(key == "ConfirmedScheduleColor")
{
var config = db.Configurations.FirstOrDefault();
return config.ConfirmedScheduleColor;
}
}
private static string GetValue(string key, string defaultValue)
{
return ConfigurationManager.AppSettings[key] ?? defaultValue;
}
private static string GetValue(string key, int defaultValue)
{
int i;
if(int.TryParse(ConfigurationManager.AppSettings[key], out i))
return i;
return defaultValue;
}
}
In EF Core you can set the check constraint for the primary key. It enforces that column Id must have value that is equal to 1 which means only one record can exist in table if you have the primary key.
modelBuilder.Entity<YourTable>(e =>
{
e.HasCheckConstraint("CK_Table_Column", "[Id] = 1");
e.HasData(...) //optionally add some initial date for Id = 1
});

MVC4 and Entity Framework Inheritance and Include

I have some simple objects
public class DataClass
{
public int id;
public string Data;
}
public class Job()
{
public int id;
}
public class NewJob : Job
{
public DateTime StartDate;
public DataClass data;
}
I have then defined them in my dBContext()
public DbSet<Job> Jobs { get; set; }
public DbSet<DataClass> DataClass { get; set; }
Now if I use the following code
NewJob job = (NewJob) db.Jobs.Find(id);
This works fine but returns "data" as null
I know I define the class with the virtual keyword and it works and populates the "data" object.
public class NewJob : Job
{
public DateTime StartDate;
public virtual DataClass data;
}
But in my case I "normally" do not want the "data" object to be populated. So I need to load it on demand.
If I try something like
NewJob job = (NewJob)db.Jobs.Include("data").First();
I get an exception
A specified Include path is not valid. The EntityType 'Models.Job' does not declare a navigation property with the name 'data'.
I guess this is because it is looking at "job" and not "NewJob" when it is trying to do the include.
I also do not like the include with a string - no design time checking.
It looks like you are trying to convert data object to your domain object via type casting which is a very bad idea. What you want to do is grab your data object, instantiate your domain object, and map your data values to the domain object using some type of helper class. A very helpful tool I have been using is Automapper. Its a tool that will allow you to map one object to another. It also allows the use of regular expression to help with the mappings if the naming conventions between the 2 objects are different.
If you're using Entity Framework Code First and want to create instances of derived classes/entities you should do the following:
using (var db = new MyDbContext())
{
var newJob = db.Jobs.Create<NewJob>();
newJob.data.Data = "some data for a new job"; // this is string Data from DataClass
db.Jobs.Add(newJob);
db.SaveChanges();
}
After a lot of searching I found the following which can help.
If you include the System.Data.Entity namespace in your using clause then you can use the extension method .Include() after OfType<>() which is not normally available.
Slightly different code sample
using System.Data.Entity;
NewJob job = (NewJob)db.Jobs.OfType<NewJob>().Include(m => m.data).Where(x => x.id == id).FirstOrDefault();
This seems to be working for me in the example I used.

SmartGWT Object binding without specifying object's fields

I am just wondering if it's possible to create some sort of binding without explicitly specifying all of the fields that need to be mapped to some widget(i.e. ListGrid).
Currently I do the following: First I read all the JSON objects fields and put these fields into CategoryRecord object like this:
public class CategoryRecord extends Record {
public CategoryRecord(String displayName, String id) {
setDisplayName(displayName);
setId(id);
}
private void setId(String id) {
setAttribute("id", id);
}
public String getId() {
return getAttributeAsString("id");
}
private void setDisplayName(String displayName) {
setAttribute("displayName", displayName);
}
public String getDisplayName() {
return getAttributeAsString("displayName");
}
}
Then I return a CategoryRecord[] object and put it into a ListGrid. But what if application developers decide to change the "id" field to "categoryId" or completely remove it. Do I have to manually change my code each time something like this happens? Or is there a way to get the whole JSON object, get it's fields and put it wherever I want, without specifying their names.
Thanks in advance!
Just iterate over the properties of the JSON object and create ListGridField objects for each one.

Persist derived objects using Mongo C# driver

I have the following class hierarchy
[BsonKnownTypes(typeof(MoveCommand))]
public abstract class Command : ICommand
{
public abstract string Name
{
get;
}
public abstract ICommandResult Execute();
}
public class MoveCommand : Command
{
public MoveCommand()
{
this.Id = ObjectId.GenerateNewId().ToString();
}
[BsonId]
public string Id { get; set; }
public override string Name
{
get { return "Move Command"; }
}
public override ICommandResult Execute()
{
return new CommandResult { Status = ExecutionStatus.InProgress };
}
}
if I save the command like so:
Command c = new MoveCommand();
MongoDataBaseInstance.GetCollection<Command>("Commands").Save(c);
and then query the DB, I don't see the derived properties persisted.
{ "_id" : "4df43312c4c2ac12a8f987e4", "_t" : "MoveCommand" }
I would expect a Name property as a key in the document.
What am I doing wrong?
Also, is there a way to avoid having a BsonKnowTypes attribute on the base class for persisting derived instances? I don't see the why a base class needs to know about derived classes. This is bad OO design and is being forced on my class hierarchy by the BSON library. Am I missing something here?
1.Name property was not saved into database because it haven't setter. Serializers not serialize properties that's haven't setters (because if serializer serialize such property it will not able deserialize it back). So if you want serialize Name property then just add fake setter(into ICommand need to add it also):
public override string Name
{
get { return "Move Command"; }
set{}
}
2.If you don't want use BsonKnownTypes attribute there is another way to notify serializer about know types it might encounter during deserialization. Just Register maps once, on app start event:
BsonClassMap.RegisterClassMap<MoveCommand>();
//all other inherited from ICommand classes need register here also
So you should use or KnownTypes attribute or register BsonClassMap for each polymorphic class, otherwise you will get 'unknown descriminator' error during deserializtion:
var commands = col.FindAllAs<ICommand>().ToList();
3 You said:
This is bad OO design and is being
forced on my class hierarchy by the
BSON library.
In any way even without KnownTypes atribute your code using Bson lib through BsonId attribute.
If you want avoid it you can:
BsonClassMap.RegisterClassMap<MoveCommand>(cm => {
cm.AutoMap();
cm.SetIdMember(cm.GetMemberMap(c => c.Id));
});
So now you can remove reference to Mongodb.Bson lib from your domain code lib.