Populating a Dictionary from a Class using Reflection - c#

I want to use a dictionary to replace words in a HTML template between two $ signs. I've got it working when I add the keys myself, but I want to be able to replace using reflection, so that if I give this project to someone else, then they only need to change the class and the template keys.
I've got the Class with some properties. I populate this class and then try to populate the dictionary.
public class FeedMessageValue
{
public string Username { get; set; }
public string SubscriptionID { get; set; }
public DateTime MessageTime { get; set; }
}
public class FeedMessageData : IMailData
{
private FeedMessageValue feedMessageValue;
public FeedMessageData(string username, string subscriptionID, DateTime messageTime)
{
this.feedMessageValue = new FeedMessageValue
{
Username = username
, SubscriptionID = subscriptionID
, MessageTime = messageTime
};
PropertyInfo[] infos = this.feedMessageValue.GetType().GetProperties();
foreach (PropertyInfo info in infos)
{
this.getMergeValues().Add(info.Name, info.GetValue(this.feedMessageValue, null).ToString());
}
}
public Dictionary<string, string> getMergeValues()
{
return new Dictionary<string, string>();
}
}
This runs through the Email Generator:
public interface IMailData
{
Dictionary<string, string> getMergeValues();
}
public interface IEmailGenerator
{
MailMessage generateEmail(IMailData mailData, string htmlTemplate, string textTemplate);
}
public class EmailGenerator : IEmailGenerator, IRegisterInIoC
{
// Setup the rules
static readonly Regex emailRegex = new Regex(#"\$([\w\-\,\.]+)\$", RegexOptions.Compiled);
private string mergeTemplate(string template, IReadOnlyDictionary<string, string> values)
{
string emailTextData = emailRegex.Replace(template, match => values[match.Groups[1].Value]);
return emailTextData;
}
public MailMessage generateEmail(IMailData mailData, string htmlTemplate, string textTemplate)
{
// MailMessage
}
}
So, in theory one of the dictionary keyvalue pairs should now be {"Username", username}, but using my code to replace for $Username$, then it throws a bug with that there is no key for Username.

The problem is with getMergeValues(). You're creating a new instance of Dictinary<string, string> each time. Change that method to a property, or have it return a field.
As it is right now, when you're looping through the PropertyInfo[], you create a new instance of Dictionary<string, string>, add { "Username", username }, then don't do anything with the reference to the Dictionary<string, string> you created. Then on the next iteration of the loop you create a second Dictionary<string, string> this one with, perhaps, { SubscriptionId, subscriptionID }, and don't do anything with the reference. And so on and so on.
public class FeedMessageData : IMailData
{
private FeedMessageValue feedMessageValue;
public FeedMessageData(string username, string subscriptionID, DateTime messageTime)
{
MergeData = new Dictionary<string, string>();
this.feedMessageValue = new FeedMessageValue
{
Username = username
, SubscriptionID = subscriptionID
, MessageTime = messageTime
};
PropertyInfo[] infos = this.feedMessageValue.GetType().GetProperties();
foreach (PropertyInfo info in infos)
{
MergeData.Add(info.Name, info.GetValue(this.feedMessageValue, null).ToString());
}
}
public Dictionary<string, string> MergeData { get; }
}

Related

How do I access a structures component in the Sorted list. sortedList.GetByIndes(i).name?

Basically how do I access the component of a structure in my Sorted List (keys are strings and values are the structure). The structure is Section and one of the components of it is called name. How do I access that component. linkedList.GetByIndex(i).name doesn't work.
To illustrate my comment:
struct A
{
public string name;
}
static void Demo()
{
// using System.Collections.Generic;
SortedList<string, A> list = new SortedList<string, A>();
list.Add("k0", new A { name = "name0" });
var name0 = list.Values[0].name;
}
To access the first struct in the example list, use list.Values[0] or list["k0"]. You can then access the .name property of the struct.
As far as I understood, the Post from #AxelKemper should help.
A simple example:
public struct Section
{
public string Name { get; set; }
public SortedList<string, string> List { get; set; }
}
public class SectionsClass
{
public string Indentifier { get; set; }
public SortedList<string, Section> Sections { get; set; }
}
public class MyTestClass
{
public MyTestClass()
{
var sc = new SectionsClass
{
Indentifier = "A",
Sections = new SortedList<string, Section> {
{"1", new Section { Name = "AA" } },
{"2", new Section { Name = "AB" } },
}
};
Debug.WriteLine(sc.Sections.ElementAt(0).Value.Name); // AA
}
}
UPDATE: insert "using System.Linq;" as "ElementAt" is an extension method from Linq

How can I set my class properties values Using Reflection

Good Day,
Lets say this is my class:
public class MyClass {
public bool boolProp { get; set; }
public string stringProp { get; set; }
}
this is my IDictionary:
IDictionary<string, string> myDict=
new IDictionary<string, string>();
myDict.Add("boolProp", "true");
myDict.Add("stringProp", "teststring");
So I want to update my class properties using Reflection where my dictionary keys matches the name of property then set its value by creating a method, how is that?
Method parameter should be like this:
public void UpdateProperties(IDictionary<string, string> myDict) {
Thanks
With GetProperty method:
IDictionary<string, string> myDict = new Dictionary<string, string>();
myDict.Add("boolProp", "true");
myDict.Add("stringProp", "teststring");
var s = new MyClass();
var t = s.GetType();
foreach (var values in myDict)
{
var p = t.GetProperty(values.Key, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
var c = TypeDescriptor.GetConverter(p.PropertyType);
var convertedValue = c.ConvertFromInvariantString(values.Value);
p.SetValue(s, convertedValue);
}

Create a dictionary of a model?

It's quite hard for me to explain this, but I will give it a go.
Objective:
Create a LINQ query that will return a dictionary of data. However it must be a dictionary of the model which I am using.
View Model:
public class ValueBySupplierAndClaimTypeViewModel : ReportViewModel
{
public IQueryable<ValueBySupplierAndClaimTypeModel> ReportData {get; set; }
public TotalValueBySupplierAndClaimTypeModel ReportTotalData { get; set; }
public Dictionary<string, decimal> DictionaryData { get; set; }
public string output { get; set; }
}
Interface:
Dictionary<string, decimal> DictData;
TotalValueBySupplierAndClaimTypeModel GetTotalValueBySupplierAndClaimType(
int ClientID, int ReviewPeriodID, int StatusCategoryID);
SQL Repository:
public TotalValueBySupplierAndClaimTypeModel GetTotalValueBySupplierAndClaimType(int ClientID, int ReviewPeriodID, int StatusCategoryID)
{
var rt =
this.GetValueBySupplierAndClaimType(ClientID, ReviewPeriodID, StatusCategoryID);
TotalValueBySupplierAndClaimTypeModel x = new TotalValueBySupplierAndClaimTypeModel()
{
NormalTotal = rt.Sum(c=>c.Normal) ?? 0,
QueryTotal = rt.Sum( c => c.Query) ?? 0,
StrongTotal = rt.Sum( c => c.Strong) ?? 0
};
return x;
}
I'm really not sure how to do this. Can anybody help?
I have this function that converts an object to a dictionary. It gets all the properties of the class, as the dictionary's keys. May be you can modify it to meet your needs:
public Dictionary<string, object> ConvertClassToDict(object classToConvert)
{
Dictionary<string, object> result = new Dictionary<string, object>();
PropertyInfo[] properties = classToConvert.GetType().GetProperties();
List<string> propertiesNames = properties.Select(p => p.Name).ToList();
foreach (var propName in propertiesNames)
{
PropertyInfo property = properties.First(srcProp => srcProp.Name == propName);
var value = property.GetValue(classToConvert, null);
result.Add(propName, value);
}
return result;
}
The argument classToConvert, is just an instance of any class.
Similar to #lukiller's answer, but with LINQ:
public Dictionary<string, object> MapToDictionary(object instance)
{
if(instance == null) return null;
return instance.GetType()
.GetProperties()
.ToDictionary(p => p.Name,
p => p.GetValue(instance));
}
For example, let's suppose we have the following class:
public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
We can print it like this (one line):
MapToDictionary(new User()
{
Username = "mcicero",
Password = "abc123"
}).ToList().ForEach(i => Console.WriteLine("{0}: {1}", i.Key, i.Value));
This prints out:
Username: mcicero
Password: abc123

How to implement Foreach in my class so I can get each key name and value?

public class Zone
{
public string zoneID { get; set; }
public string zoneName { get; set; }
public string zonePID { get; set; }
}
I want to use foreach for Zone, like
var zone = new Zone(){zoneId = "001", zoneName = "test"};
foreach(var field in zone)
{
string filedName = field.Key; //for example : "zoneId"
string filedValue = filed.value; //for example : "001"
}
I just don't konw how to implement GetEnumerator() in Zone class
You can't enumerate the properties of a class (in a simple way)
Use a string array or string list or a dictionary inside your class.
Note: Indeed it is possible to enumerate the properties of a class using Reflection, but this is not the way to go in your case.
foreach(var field in zone)
{
string filedName = field.zoneID; //Id of property from Zone Class
string filedValue = filed.zoneName ; //name of property from Zone Class
}
You could equip Zone with this method:
public Dictionary<string, string> AsDictionary()
{
return new Dictionary<string, string>
{
{ "zoneID", zoneID },
{ "zoneName", zoneName },
{ "zonePid", zonePid },
};
}
Then you can foreach that.
Alternatively, you can implement GetEnumerator() as an iterator block where you yield return the three new KeyValuePair<string, string>.
I am not saying that this design is particularly recommendable.
Thanks eveyrone! It Seems I need to use reflection to achieve the goal.
System.Reflection.PropertyInfo[] pis = zone.GetType().GetProperties();
foreach (var prop in pis)
{
if (prop.PropertyType.Equals(typeof(string)))
{
string key = prop.Name;
string value = (string)prop.GetValue(zome, null);
dict.Add(key, value); //the type of dict is Dictionary<str,str>
}
}
Just don't know wheather this is a good solution.

Create Json Array with ServiceStack

Quite new to .NET. Still haven't gotten the hang of how to do dictionaries, lists, arrays, etc.
I need to produce this JSON in order to talk to SugarCRM's REST API:
{
"name_value_list": {
"assigned_user_name": {
"name": "assigned_user_name",
"value": "joe"
},
"modified_by_name": {
"name": "modified_by_name",
"value": "jill"
},
"created_by_name": {
"name": "created_by_name",
"value": "jack"
}
}
}
from this C# POCO, which plays nicely with ServiceStack:
public class lead {
public string assigned_user_name { get; set; }
public string modified_by_name { get; set; }
public string created_by_name { get; set; }
}
I have to do this sort of conversion for lots of different classes, so I don't think it's wise to create another strongly typed class (ala Costomising the serialisation/serialised JSON in service stack)
I've looked through the ServiceStack docs, but maybe I missed an example of this somewhere.
How do I build this JSON in a way that I can extend to other ServiceStack POCOs?
This produces the right JSON:
Dictionary<string, Dictionary<string, string>> nameValues = new Dictionary<string, Dictionary<string, string>>();
// Deal with all the properties on the object
IList<PropertyInfo> props = new List<PropertyInfo>(this.GetType().GetProperties());
foreach (PropertyInfo prop in props)
{
Dictionary<string, string> nameValue = new Dictionary<string, string>();
nameValue.Add("name", prop.Name);
object propValue = prop.GetValue(this, null);
if (propValue == null)
{
nameValue.Add("value", string.Empty);
}
else
{
nameValue.Add("value", prop.GetValue(this, null).ToString());
}
nameValues.Add(prop.Name, nameValue);
}
Dictionary<string, object> nameValuesArray = new Dictionary<string, object>();
nameValuesArray.Add("name_value_list", nameValues);
string jsonString = JsonSerializer.SerializeToString<Dictionary<string, object>>(nameValuesArray);
The reflection stuff is so that I can use it on any object later.
It's just a matter of constructing the right dictionary for the desired JSON output - in this case a dictionary -> dictionary -> dictionary. Trial and error... :/
Update
Altered it slightly (thanks paaschpa) to use a generic NameValue class because Dictionaries look ugly. I also got the requirements wrong. The JSON should be this:
[
{
"name": "id",
"value": "60e03cb3-df91-02bd-91ae-51cb04f937bf"
},
{
"name": "first_name",
"value": "FancyPants"
}
]
which you can do like this:
public class NameValue
{
public string name { get; set; }
public string value { get; set; }
}
public class Lead
{
public string assigned_user_name { get; set; }
public string modified_by_name { get; set; }
public string modified_user_name { get; set; }
public List<NameValue> toNameValues()
{
List<NameValue> nameValues = new List<NameValue>();
IList<PropertyInfo> props = new List<PropertyInfo>(this.GetType().GetProperties());
foreach (PropertyInfo prop in props)
{
NameValue nameValue = new NameValue();
object propValue = prop.GetValue(this, null);
if (propValue != null && !String.IsNullOrEmpty(propValue.ToString()))
{
nameValue.name = prop.Name;
nameValue.value = propValue.ToString();
nameValues.Add(nameValue);
}
}
return nameValues;
}
}
I'm leaving my original question as is (and my above answer) because it's still a legit example and proper JSON.
Well, I don't think .NET dictionaries, lists, arrays, etc. will be helpful since the JSON you listed doesn't appear to have any arrays (square brackets) it in. I'm guessing most .NET JSON serializers will use square brackets when it hits these types. So, I think this leaves creating your own classes or doing some type of 'string magic' to produce to JSON you need.
Not exactly sure how you are using ServiceStack to talk to SugarCRM, but doing something like below should have ServiceStack.Text.JsonSerializer produce the JSON string you listed.
public class NameValue
{
public string name { get; set; }
public string value { get; set; }
}
public class Lead
{
public NameValue assigned_user_name { get; set; }
public NameValue modified_by_name { get; set; }
public NameValue created_by_name { get; set; }
}
public class LeadRequest
{
public Lead name_value_list { get; set; }
}
public void JsonTest()
{
var req = new LeadRequest
{
name_value_list = new Lead
{
assigned_user_name = new NameValue {name = "assigned_user_name", value = "joe"},
modified_by_name = new NameValue {name = "modified_by_name", value = "jill"},
created_by_name = new NameValue {name = "created_by_name", value = "jack"}
}
};
var jsonReq = ServiceStack.Text.JsonSerializer.SerializeToString(req);
}
You could create a custom serializer for the lead class.
JsConfig<lead>.SerializeFn = lead => {
// Use reflection to loop over the properties of the `lead` object and build a dictionary
var data = new Dictionary<string, object>();
foreach (var property in typeof(lead).GetProperties()) {
data[property.Name] = new {
name: property.Name,
value: property.GetValue(lead, null);
};
}
return data.ToJson();
};
You could make this generic by having all classes that you want to serialize in this way implement a marker interface, for example ISugarCrmRequest, and register this custom serializer for all implementations of that interface.

Categories