Converting a resource set into dictionary using linq - c#

var rm = new ResourceManager(sometype);
var resourceSet = rm.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
I want to convert the above resource set into dictionary. Currently I'm doing through manually by looping as below.
var resourceDictionary = new Dictionary<string, string>();
foreach (var r in resourceSet)
{
var dicEntry = (DictionaryEntry)r;
resourceDictionary.Add(dicEntry.Key.ToString(), dicEntry.Value.ToString());
}
How I can do achieve that easily using linq?

Try this:
var resourceDictionary = resourceSet.Cast<DictionaryEntry>()
.ToDictionary(r => r.Key.ToString(),
r => r.Value.ToString());

var resourceDictionary = resourceSet.Select(r => (DictionaryEntry) r)
.ToDictionary(dicEntry => dicEntry.Key.ToString(),
dicEntry => dicEntry.Value.ToString());

Related

accessing json property with given values

var orderJson = JsonConvert.DeserializeObject<dynamic>(httpResultStr);
var orderidCount = orderJson.data.orderUuids.Count;
for (int i = 0; i <= orderidCount; i++)
{
var orderId = orderJson.data.orderUuids[i]; // my fail attempt. Didnt work
var map = orderJson.data.ordersMap;
foreach (var d in map)
{
var receipt = d.fareInfo.totalPrice;
Console.WriteLine(receipt);
}
}
Im trying to access the ordersMap members with the given values in orderUuids object. Inside the ordersMap Ids contain the fareInfo.totalPrice property that I'm trying to access. How would I go about achieving this?
[![json tree with ordersMap. Trying to access its members with the given values in orderUuids object.][1]][1]
You can make a partial/full map using the JSON file and use JsonConvert.DeserializeObject<>(json).
Other solution could be create a partial map using an anonymous type. Here is a code snip.
var anonymousTypeObject = new
{
status = "",
data = new
{
ordersMap = new Dictionary<string, JToken>(),
orderUuids = new string[0]
}
};
var obj = JsonConvert.DeserializeAnonymousType(json, anonymousTypeObject);
foreach (var kvp in obj.data.ordersMap)
{
var totalPrice = kvp.Value["fareInfo"]?["totalPrice"]?.ToString();
Debug.WriteLine($"{kvp.Key} -> {totalPrice}");
}
EDIT If you don't want any map use this solution.
var jObj = JsonConvert.DeserializeObject<JObject>(json);
var orderUuids = jObj.SelectToken("data.orderUuids")?.Values<string>();
foreach (var orderUuid in orderUuids)
{
var totalPrice = jObj.SelectToken($"data.ordersMap.{orderUuid}.fareInfo.totalPrice")?.Value<double>();
Debug.WriteLine($"{orderUuid} -> {totalPrice}");
}

How can I specify the editorconfig-derived OptionSet for an AdhocWorkspace in Roslyn?

Roslyn will let me add files to an AdhocWorkspace and run a formatter on them but I do not see how I can specify the formatting options. I want to derive them from a .editorconfig file passed in on the command line
var adhoc = new AdhocWorkspace();
var solutionInfo = SolutionInfo.Create(SolutionId.CreateNewId(),
VersionStamp.Default,
"MySolution");
adhoc.AddSolution(solutionInfo);
var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(),
VersionStamp.Default,
"MyProject",
"MyProject.dll",
Microsoft.CodeAnalysis.LanguageNames.CSharp);
adhoc.AddProject(projectInfo);
foreach(var arg in args) {
var sourceText = SourceText.From(File.OpenText(arg).BaseStream);
adhoc.AddDocument(projectInfo.Id, arg, sourceText);
}
foreach(var document in adhoc.CurrentSolution.Projects.First().Documents){
var formattedDocument = Formatter.FormatAsync(document, adhoc.Options).Result;
var formattedText = formattedDocument.GetTextAsync().Result;
Console.WriteLine(formattedText);
}
adhoc.Options = adhoc.Options.WithChangedOption(...) will let me change a single option but I want the options to come from a .editorconfig file. Is there an API that will let me do this?
I found this project: https://github.com/dotnet/format
You can find the code here:
https://github.com/dotnet/format/blob/afc9284d4fb44cb695e17f10d2268944471a5c3b/src/Utilities/EditorConfigOptionsApplier.cs
I understood how it works and simplified it like this for parsing the .editorconfig:
public static OptionSet SimplifiedParsing(Workspace space)
{
OptionSet optionsSet = space.Options;
//reading .editorconfig
var editorConfigDictionary = File.ReadAllLines(#".editorconfig")
//here I take only the ones for csharp
.Where(x => x.StartsWith("csharp"))
.Select(x => x.Split(" = "))
.ToDictionary(x => x[0], y => y[1]);
var commonOptionsType = typeof(FormattingOptions);
var csharpOptionsType = typeof(CSharpFormattingOptions);
var formattingTypes = new[] {commonOptionsType, csharpOptionsType};
var optionType = typeof(IOption);
//here we are filtering all the methods from formattingTypes classes, with reflection, which parse the options by keys which are in editor config
var allParsingMethods = formattingTypes
.SelectMany(t => t.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.GetProperty))
.Where(p => optionType.IsAssignableFrom(p.PropertyType))
.Select(p => (IOption) p.GetValue(null))
.Select(GetParsingMethod)
.Where(ows => ows.Item2 != null)
.ToImmutableArray();
foreach ((IOption, OptionStorageLocation, MethodInfo) parsingMethod in allParsingMethods)
{
//taking info for invoking TryGetOption
var (option, editorConfigStorage, tryGetOptionMethod) = parsingMethod;
object result = null;
//arguments for reflection invocation
var args = new[] {editorConfigDictionary, option.Type, result};
//editorConfigStorage instance on which to call the method
//invoking bool TryGetOption(IReadOnlyDictionary<string, string> rawOptions, Type type, out object result)
var isOptionPresent = (bool) tryGetOptionMethod.Invoke(editorConfigStorage, args);
result = args[2];
if (isOptionPresent)
{
var optionKey = new OptionKey(option, option.IsPerLanguage ? LanguageNames.CSharp : null);
//if option is parsed -> its present and we can add it to OptionSet
optionsSet = optionsSet.WithChangedOption(optionKey, result);
}
}
return optionsSet;
//helpers
(IOption, OptionStorageLocation, MethodInfo) GetParsingMethod(IOption option)
{
var editorConfigStorage = option.StorageLocations.IsDefaultOrEmpty
? null
: option.StorageLocations.FirstOrDefault(IsEditorConfigStorage);
//getting TryGetOption method of EditorConfigStorageLocation<T>
// original method signature:
// public bool TryGetOption(IReadOnlyDictionary<string, string> rawOptions, Type type, out object result)
var tryGetOptionMethod = editorConfigStorage?.GetType().GetMethod("TryGetOption");
return (option, editorConfigStorage, tryGetOptionMethod);
}
bool IsEditorConfigStorage(OptionStorageLocation storageLocation)
{
return storageLocation.GetType().FullName
.StartsWith("Microsoft.CodeAnalysis.Options.EditorConfigStorageLocation");
}
}

Creating method to use one foreach instead multiple

I'm working with c#, and I have working code where I repeated same code every line, and that's because I'm creating list, conversions , extracting data etc.
So I have multiple foreach clauses,multiple lists, multiple conversions of list to datatables. My question is, what can I do to re-factorize this in order to have clean code?
Code:
private void BtnLoadReport_Click(object sender, EventArgs e)
{
var db = new SQLDataMgr();
List<string> DesignStatusList = new List<string>();
List<string> ShopStatusList = new List<string>();
List<string> CustomerTypeList = new List<string>();
List<string> CustomerList = new List<string>();
List<string> ResellerList = new List<string>();
List<string> StateList = new List<string>();
List<string> ProjectManagerList = new List<string>();
List<string> SalesRepresentativeList = new List<string>();
var checkedDesignStatus = cboDesignStatus.CheckBoxItems.Where(x => x.Checked);
var checkedShopStatus = cboShopStatus.CheckBoxItems.Where(x => x.Checked);
var checkedCustomerType = cboShopStatus.CheckBoxItems.Where(x => x.Check
var checkedCustomer = cboShopStatus.CheckBoxItems.Where(x => x.Checked);
var checkedReseller = cboShopStatus.CheckBoxItems.Where(x => x.Checked);
var checkedState = cboShopStatus.CheckBoxItems.Where(x => x.Checked);
var checkedProjectManager = cboShopStatus.CheckBoxItems.Where(x => x.Checked);
var checkedSalesRepresentative = cboShopStatus.CheckBoxItems.Where(x => x.Checked);
foreach (var i in checkedDesignStatus)
{
DesignStatusList.Add(i.Text);
}
foreach (var i in checkedShopStatus)
{
ShopStatusList.Add(i.Text);
}
foreach (var i in checkedCustomerType)
{
CustomerTypeList.Add(i.Text);
}
foreach (var i in checkedCustomer)
{
CustomerList.Add(i.Text);
}
foreach (var i in checkedReseller)
{
ResellerList.Add(i.Text);
}
foreach (var i in checkedState)
{
StateList.Add(i.Text);
}
foreach (var i in checkedProjectManager)
{
ProjectManagerList.Add(i.Text);
}
foreach (var i in checkedSalesRepresentative)
{
SalesRepresentativeList.Add(i.Text);
}
DataTable designStatusParameters = ToStringDataTable(DesignStatusList);
DataTable shopStatusParameters = ToStringDataTable(ShopStatusList);
DataTable customerTypeParameters = ToStringDataTable(CustomerTypeList);
DataTable customerParameters = ToStringDataTable(CustomerList);
DataTable resellerParameters = ToStringDataTable(ResellerList);
DataTable stateParameters = ToStringDataTable(StateList);
DataTable projectManagerParameters = ToStringDataTable(ProjectManagerList);
DataTable salesRepresentativerParameters = ToStringDataTable(SalesRepresentativeList);
}
Change ToStringDataTable to an Extension Method. Then:
var designStatusParameters = cboDesignStatus.CheckBoxItems.Where(x => x.Checked)
.Select(i => i.Text).ToList().ToStringDataTable();
You can even write the extension method for your control in a way that performs filtering, projection and converting to data table for you then you can have:
var designStatusParameters = cboDesignStatus.ToStringDataTable();
You can cut out all the foreach loops by using Linq's Select():
For example:
var DesignStatusList =
cboDesignStatus.CheckBoxItems
.Where(x => x.Checked)
.Select(i => i.Text)
.ToList();
That will leave you with a List<string> containing all the Text properties from the checked CheckBoxes.
You could even skip declaring the list and combine that with your DataTable creation lines:
var designStatusParameters = ToStringDataTable(
cboDesignStatus.CheckBoxItems
.Where(x => x.Checked)
.Select(i => i.Text)
.ToList());
I would suggest putting this in a method of its own rather than repeating this over and over for each group of checkboxes.
Just keep in mind that less lines of code doesn't mean faster performance. It still has to iterate through the lists to find the right values. But it is much more readable than being hit in the face with a wall of repetitive code.
You don't need those many foreach rather re-factor to a single method like
public void AddToList(List<string> listToAdd, List<CheckBox> listToIterate)
{
foreach (var i in listToIterate)
{
listToAdd.Add(i.Text);
}
}
You are taking unnecessary expicit steps making your code way more verbose than it should be.
You are doing in separate steps:
Make an empty list.
Filter data
Iterate filtered data and add it to the empty list.
When you can do:
var newList =
someCollection.Where(someFilter)
.Select(someProjection)
.ToList();
That will make the code much more readable.
And, if you are in the mood, you can even make a helper method where you pass in someCollection, someFilter and someProjection and returns a list of something.
The code below isn't quite right, but I'd recommend that you build one generic method that returns a DataTable and you call that method over and over. Something like this:
public DataTable getDataTable( CheckBox yourCheckBox)
{
DataTable returnTable = new DataTable();
List<string> tempList = new List<string>();
var checkedDesignStatus = yourCheckBox.CheckBoxItems.Where(x => x.Checked);
foreach (var i in checkedDesignStatus)
{
tempList.Add(i.Text);
}
returnTable = ToStringDataTable(tempList);
return returnTable;
}
Create method (maybe local method?)
DataTable CheckedToDataTable(YourContainerType container)
=> ToStringDataTable(container.CheckBoxItems.Where(x => x.Checked).Select(x => x.Text).ToList());

Cannot convert type 'Newtonsoft.Json.Linq.JProperty' to 'System.Collections.Generic.KeyValuePair<string,object>'

var stringResult = {"reporting":{"default":{"Outpatient":8045376.0,"OutpatientPMPM":101.6472,"totalWorkersCompClaimsPaid":7718428.46,"totalWorkersCompClaimsPaidPMPM":97.5165,"totalMedicalPaidAmount":1.6883294E7,"totalMedicalPaidAmountPMPM":213.3076,"totalVisionClaimsPaid":2837.69,"totalVisionClaimsPaidPMPM":0.0359,"totalPharmacyPaidAmount":2.478251486E7,"totalPharmacyPaidAmountPMPM":313.1082,"totalDentalClaimsPaid":12271.67,"totalDentalClaimsPaidPMPM":0.155,"employeeMonths":35415.0,"memberMonths":79150.0,"subscribers":3009.0,"totalVendorPaidAmount":97034.0,"totalVendorPaidAmountPMPM":1.226,"Office":4285314.0,"OfficePMPM":54.1417,"Inpatient":4552604.0,"InpatientPMPM":57.5187,"members":6741.0,"totalHealthPlanClaimsPaid":4.949638068000001E7,"averageFamilySize":2.2403,"totalHealthPlanClaimsPaidPMPM":625.3492}}}
dynamic json = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(stringResult);
float value = json.reporting.#default.totalPharmacyPaidAmount;
foreach (KeyValuePair<string, dynamic> page in json.reporting.#default)
{
var key = page.Key;
var totalHealthPlanClaimsPaid = page.Value.totalHealthPlanClaimsPaid;
var averageFamilySize = page.Value.averageFamilySize;
}
I am getting an error in foreach loop as
Cannot convert type 'Newtonsoft.Json.Linq.JProperty' to
'System.Collections.Generic.KeyValuePair'.
while performing the above task where I am doing wrong.
json.reporting.#default returns Newtonsoft.Json.Linq.JProperty, change your code:
foreach (KeyValuePair<string, dynamic> page in json.reporting.#default.Children())
{
var key = page.Key;
var totalHealthPlanClaimsPaid = page.Value.totalHealthPlanClaimsPaid;
var averageFamilySize = page.Value.averageFamilySize;
}
docs for read about it http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JProperty.htm
What #progpow said is right. You can also convert the result set into a dictionary and iterate through it.
Dictionary<string, dynamic> result = json.reporting.#default.ToObject<Dictionary<string,dynamic>>();
foreach (KeyValuePair<string,dynamic> page in result)
{
var key = page.Key;
var totalHealthPlanClaimsPaid = page.Value.totalHealthPlanClaimsPaid;
var averageFamilySize = page.Value.averageFamilySize;
}

Can we make this more terse with linq?

I am curious if there is a way where I can capture the lower lines (the creation of the dictionary and loop to add values) in the linq statement itself. Right now the select new returns a new anonymous type but I am wondering if there is a way to make it return a Dictionary with all the values pre-populated.
XDocument reader = XDocument.Load("sl.config");
var configValues = from s in reader.Descendants("add") select new { Key = s.Attribute("key").Value, s.Attribute("value").Value };
Dictionary<string, string> Settings = new Dictionary<string, string>();
foreach (var s in configValues)
{
Settings.Add(s.Key, s.Value);
}
Try Enumerable.ToDictionary extension method.
XDocument reader = XDocument.Load("sl.config");
var Settings = reader.Descendants("add")
.ToDictionary(s => s.Attribute("key").Value, s => s.Attribute("value").Value);
var = XDocument.Load("sl.config").Descendants("add").ToDictionary
(x => x.Attribute("key"). Value, x => x.Attribute("value"). Value);

Categories