unity dictionary value return null - dictionary

i have Dictionary "DebugCommands" in DebugCommandBase
public class DebugCommandBase
{
private string _id;
private string _description;
private string _format;
public static Dictionary<string, DebugCommandBase> DebugCommands;
public DebugCommandBase(string id, string description, string format)
{
if (DebugCommands == null)
DebugCommands = new Dictionary<string, DebugCommandBase>();
string mainKeyword = format.Split(' ')[0];
DebugCommands[mainKeyword] = this;
}
public string Id => _id;
public string Description => _description;
public string Format => _format;
}
new DebugCommand("test_command", "test", "test_command", () =>
{
//any command
});
In general, everything works well, but when I try to get a value from a dictionary, I get null
foreach (DebugCommandBase command in DebugCommandBase.DebugCommands.Values)
{
print(command.Description);
//return null
}
OR
print(DebugCommandBase.DebugCommands["test_command"].Format); //return null
what is the correct way to get the value from such a dictionary?

Did you in fact check the command has a populated Description?
Normally, your approach of accessing the values in a dictionary is correct. A similar opportunity to access the values of a dictionary entry is possible by a slight change of code. You'd access each dictionary entry as a keyvaluepair.
foreach (KeyValuePair<string, DebugCommandBase> dEntry in DebugCommamdBase.DebugCommands)
{
print(dEntry.Value.Description);
}

Related

SmartFormat best way to serialize a dictionary

I have a data object with an dictionary.
Now I want to serialize this dictionary to a json string.
Is it possible to do this inside the template?
public string GenerateTest()
{
Dictionary<string, object> dataDictionary = new Dictionary<string, object>();
dataDictionary.Add("Testdata1", "Value1");
dataDictionary.Add("Testdata2", "Value2");
string result = Smart.Format(CultureInfo.InvariantCulture, "{data.someFormattertoGetAnJsonString}", new {data= dataDictionary });
Console.WriteLine(result);
return result;
}
Sure you could do that, but not in a generic way. SmartFormat is a formatter, rather than a serializer. So in general, SmartFormat is best in filling a text template with data, like it is required with mail merge.
In your case, you'll be better off using serializers like System.Text.Json or Newtonsoft.Json.
For the latter, here is an example how simple this works: https://www.newtonsoft.com/json/help/html/serializedictionary.htm
I have attached my solution. You have to register the ToJSONFormatter with the AddExtensions Method. After that you can call it like this: {MyVariable:ToJSON()}
Smart.Default.AddExtensions(new ToJSONFormatter());
public class ToJSONFormatter : IFormatter
{
public string Name { get; set; } = "ToJSON";
public bool CanAutoDetect { get; set; } = false;
private JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { DateFormatString = "yyyy-MM-ddTHH:mm:ss" };
//{Data:ToJSON()}
public bool TryEvaluateFormat(IFormattingInfo formattingInfo)
{
formattingInfo.Write(JsonConvert.SerializeObject(formattingInfo.CurrentValue));
return true;
}
}

Parse JObject into a mixed object (static + dynamic fields)

given the following json
{
"$$href": "http://localhost:8080/url1",
"name": "Sebastian Slutzky"
}
I'd like to deserialize it into an object like this one
public class DomainObject
{
[JsonProperty("$$href")]
public string href { get; set; }
public JObject this[string key] => throw new NotImplementedException();
}
so that arbitrary properties (like name can be accessed dynamically)
var href = domainObject.href;
var name = domainObject["name"] as string;
My current implementation is by passing the JObject to the constructor of my object, and decorate it (i.e. composition). Is there a way of solving this by inheritance instead (i.e. by extending JObject?
Any other solution?
You could make use of JsonExtensionData. For example
public class DomainObject
{
[JsonProperty("$$href")]
public string href { get; set; }
[JsonExtensionData]
private IDictionary<string, JToken> UnknownTypes;
public JToken this[string key] => UnknownTypes[key];
}
The Indexer now allows you to retrieve the values of dynamic properties with key as the following.
var result = JsonConvert.DeserializeObject<DomainObject>(json);
var name = result["name"].Value<string>();

Building LINQ query from parameters

Consider a simple Employee class.
Class Employee
{
public String FirstName {get; set;}
public int Id {get; set;}
public int Marks {get; set;}
public String LastName {get; set;}
}
So for selecting by LINQ query we can write.
var query = Employee.Where(i => i.Id > 2).OrderBy(i => i.Marks);
So can we create a function which takes 2 parameter where we can send Id and Marks.
So that i can make a function call and pass parameter what ever i need like.
var query = Employee.Where(i => i.Marks > 2).OrderBy(i => i.FirstName);
Sample looking function where we can pass any parameter
Public String GetQuery(String para1,String para2,......)
{
var query = Employee.Where(i => i.para1 > 2).OrderBy(i => i.para2);
return query;
}
or
Public String GetQuery(String para1,String para2,......)
{
String str1=para1...... // with some format included
String str2=para2...... // with some format included
var query = Employee.Where(str1).OrderBy(str2);
return query;
}
The concept is that i want to create a common(generic) query in which i can select values
of any type of parameter passed.
A type safe solution could use delegates instead of strings:
IEnumerable<Employee> employees = getExampleData();
IEnumerable<Employee> example1 = Query.Employees(employees, Query.UseID, Query.UseMarks);
IEnumerable<Employee> example2 = Query.Employees(employees, Query.UseMarks, Query.UseFirstName);
I made a helper class Query to wrap the functionality:
static class Query
{
public static int UseID(Employee employee, int i) { return employee.Id; }
public static int UseMarks(Employee employee, int i) { return employee.Marks; }
public static string UseFirstName(Employee employee, string s) { return employee.FirstName; }
public static string UseLastName(Employee employee, string s) { return employee.LastName; }
static public IEnumerable<Employee> Employees(IEnumerable<Employee> employees, func_returnInt where, func_returnInt orderby)
{
return employees.Where(i => where(i, 0) > 2).OrderBy(i => orderby(i, 0));
}
static public IEnumerable<Employee> Employees(IEnumerable<Employee> employees, func_returnInt where, func_returnString orderby)
{
return employees.Where(i => where(i, 0) > 2).OrderBy(i => orderby(i, ""));
}
}
public delegate int func_returnInt(Employee employee, int i);
public delegate string func_returnString(Employee employee, string s);
You have to use Expression : LambdaExpression.
http://msdn.microsoft.com/en-us/library/bb335710.aspx.
In my code i have used something similar:
private User GetUser(Expression<Func<User, bool>> query)
{
User user = context.Users.Where(query).FirstOrDefault();
if (user == null)
{
throw new ProviderException("The supplied user name could not be found.");
}
return user;
}
User user = GetUser(u => u.Marks == 123);
User user = GetUser(u => u.FirstName== "abc");

Creating a drop down menu with DIctionary Item

I have the following in my View:
#Html.DropDownListFor(model => model.Search, new SelectList(Model.SearchOptions))
In my Search Object I have:
public List<string> Search { get; set; }
public Dictionary<string, string> SearchOptions { get; set; }
public SearchModel GetDropDownOptions(SearchModel model)
{
model.SearchOptions = HelperModel.GetRefValues(db, Constants.SEARCH, false);
return model;
}
With it calling:
public static Dictionary<String, String> GetRefValues(DBEntities db, string refType, bool addEmpty)
{
Dictionary<String, String> res = (from c in db.References
where c.Type == refType
select c).ToDictionary(c => c.Key.ToString(),
c => c.Value.ToString());
if (addEmpty)
res.Add("", "");
return res;
}
I however get an error stating: "Object reference not set to an instance of an object."
Suggestions appreciated.
Thanks.
You should validate the parameters of all public methods. So your method:
GetRefValues(DBEntities db, string refType, bool addEmpty)
should include a check to see if db is null and if refType is null. If you do that you'll be able to see which of those two are null and then you can fix your code accordingly by tracing back to see where they are initialized (or not, as the case may be.)

Reflection C# question

I am having problem getting values of a class whose one property is another class.
Here is an example:
public class Person
{
private int age;
private string name;
public Person()
{
Address = new Address();
}
public int Age
{
get { return age; }
set { age = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public Address Address { get; set; }
}
public class Address
{
public string street { get; set; }
public string houseno { get; set; }
}
public class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Age = 27;
person.Name = "Fernando Vezzali";
person.Address.houseno = "123";
person.Address.street = "albert street";
Type type = typeof(Person);
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
Console.WriteLine("{0} = {1}", property.Name, property.GetValue(person, null));
}
}
}
But with this I dont get values of address.
Can someone help here?
Here is the possible ToString, taking into account the Jason's answer...
You can also cast your returned reflected objet into an Address to access the full object and properties
public class Address
{
public string street { get; set; }
public string houseno { get; set; }
public override ToString() {
return string.Format("street: {0}, house: {1}", street, houseno);
}
}
type.GetProperties() only gets the properties for that type, one of which is an object Address. street and houseno are not properties on Person.
Console.Write... implicitly calls ToString() on each parameter. So you probably see "Address - Namespace.Address" as an output, because someAddressObject.ToString() will return the type name.
The easiest way to get what you want for this specific situation is to override ToString() on your Address object to output some meaningful string representation of the object:
public override ToString()
{
return string.Format("#{0} {1}",
this.houseno,
this.street); //returns #123 StreetName
}
If you actually need to write every property of every sub-object on your object, that can get fairly complex - you're essentially talking about serialization, which recurses down an object tree and into each object.
Either you need to implement ToString() in Address, if you're happy with returning a formatted string as the value of Address, or your iteration code needs to inspect each property to determine whether that property's type also exposes properties, and enqueue it for further inspection.
Your foreach is iterating through all properties properly, and I beleive it is implicitely calling ToString on it to get the value, so override the ToString method of your Address class, and return the properties as a string.
Or, in the foreach, test to see if your property is a value type or a class type by getting the property type and checking IsValueType or IsClass. If IsValueType is false, then iterate through the properties of that properties' class type just as you did for the properties of Person.
Something like this (You may need to tweek to get this to compile, but it gives you the idea):
Person person = new Person();
person.Age = 27;
person.Name = "Fernando Vezzali";
person.Address.houseno = "123";
person.Address.street = "albert street";
Type type = person.GetType();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
//get the type of this property
Type tyProperty = property.PropertyType;
object oValue = property.GetValue(person, null));
//if the property is a value
if (tyProperty.IsValueType)
{
Console.WriteLine("{0} = {1}", property.Name, oValue);
}
else //else if property type is a class
{
oSubValue = property.GetValue(oValue, null));
//loop through the classes properties
PropertyInfo[] lstSubProperties = tyProperty.GetProperties();
foreach (PropertyInfo propSub in lstSubProperties)
{
Console.WriteLine("{0} = {1}", propSub .Name, oSubValue);
}
}
}

Resources