Broadcom
Connection Name: Local Area Connection
DHCP Enabled: No
IP address(es)
[01]: abc.de.fg.h
I would like to put this into a Dictionary<string, Dictionary <string, string>>
So Broadcom would be the key in the first dictionary and the rest would be value the value. The value should be stored as a dictionary where Connection Name is the key and Local Area Connection is the value. How do I go about doing that? I am new to programming. Thanks for the help.
Please do yourself a great favour and use a class for that, because in two months time you will not understand your code:
public class WhatIsThis {
private List<IPAddress> ipAddresses = new List<IPAddress>();
public string Name { get; set; }
public string ConnectionName { get; set; }
public bool DHCPEnabled { get; set; }
public List<IPAddress> IPAddresses { get return ipAddresses; }
}
Now you can keep a List<WhatIsThis> around. If you have justa few of them, the O(n) cost of looking a value up is negligible. If you want a lookup by name in O(1) fashion, you can map to a Dictionary as such:
var dict = listOfWhatisThis.ToDictionary(k=>k.Name, v=>v}
Gives you a Dictionary of type Dictionary<string,WhatIsThis> . What do you think, will you understand this better in 2 weeks time, or rather your scary Dictionary?
http://msdn.microsoft.com/en-us/library/bb531208.aspx
var dic = new dictionary<string, dictionary <string, string>>(
{"Broadcom",
new dictionary <string, string>(
{
{"Connection Name", "Local Area Connection"},
{"DHCP Enabled", "No"},
{"IP address(es) [01]", "abc.de.fg.h"}
}
)
}
);
My only concern would be that the IP Addresses should themselves be in a dictionary within the settings for a connection, not a single string, and thus the sub-dictionary would need to be dictionary<string, object>.
Similar to flq's answer, here's a more comprehensive solution which makes both subdictionaries:
using System.Collections.Generic;
using System.Linq;
namespace LINQDictionaryDemo
{
public class IPAddress
{
public int Index { get; private set; }
public string Value { get; private set; }
public IPAddress(int Index, string Value)
{
this.Index = Index;
this.Value = Value;
}
}
public class NetworkConnection
{
public string Name { get; set; }
public string ConnectionName { get; set; }
public bool DHCPEnabled { get; set; }
public List<IPAddress> IPAddresses { get; set; }
public Dictionary<string, object> ToDictionary()
{
return new Dictionary<string, object>
{
{ "ConnectionName", ConnectionName }
, { "DHCPEnabled", DHCPEnabled.ToString() }
, {"IPAddresses", IPAddresses.ToDictionary(k => k.Index, v => v.Value)}
};
}
}
public static class Demo
{
public static void Run()
{
var lnc = new List<NetworkConnection>
{
new NetworkConnection
{
Name = "Broadcom",
ConnectionName = "Local Area Connection",
DHCPEnabled = false,
IPAddresses = new List<IPAddress> {new IPAddress(1, "abc.de.fg.h")}
}
};
var dic = lnc.ToDictionary(k => k.Name, v => v.ToDictionary());
}
}
}
Related
I really don't like to hard code the name of properties of my models. So I came up with this code so far. My code is working fine and it does exactly what I want but in an ugly way. I'm pretty sure it will be problematic soon. So any help to improve it and make it work in the right way is appreciated. I'm looking to fine better way to extract selected property names without converting expression body to string. Any change to any part of this class is fine with me. Even changing usage as long as I don't hard code my property names.
What is the better way to extract selected properties name of a model?
Here is my code:
public class Selector<T> : IDisposable
{
Dictionary<string, Func<T, object>> Selectors = new Dictionary<string, Func<T, object>>();
public Selector(params Expression<Func<T, object>>[] Selector)
{
foreach (var select in Selector)
{
//string MemberName = CleanNamesUp(select.Body.ToString());
//Func<T, object> NewSelector = select.Compile();
#region Ugly Part 1
Selectors.Add(CleanNamesUp(select.Body.ToString()), select.Compile());
#endregion
}
}
#region I am Doing This So I can Use Using(var sl = new Selector<T>())
public void Dispose()
{
Selectors.Clear();
Selectors = null;
}
#endregion
#region Ugly Part 2
private string CleanNamesUp(string nameStr)
{
string name = nameStr.Split('.')[1];
if (name.Contains(","))
{
name = name.Split(',')[0];
}
return name;
}
#endregion
public Dictionary<string, object> GetFields(T Item)
{
Dictionary<string,object> SetFieldList = new Dictionary<string, object>();
foreach(var select in Selectors)
{
SetFieldList.Add( select.Key , select.Value(Item));
}
return SetFieldList;
}
public List<Dictionary<string, object>> GetFields(IEnumerable<T> Items)
{
List<Dictionary<string, object>> SetFieldListMain = new List<Dictionary<string, object>>();
foreach (var item in Items)
{
Dictionary<string, object> SetFieldList = new Dictionary<string, object>();
foreach (var select in Selectors)
{
SetFieldList.Add(select.Key, select.Value(item));
}
SetFieldListMain.Add( SetFieldList);
}
return SetFieldListMain;
}
internal List<string> GetKeys()
{
return new List<string>(this.Selectors.Keys);
}
}
This is my model:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public bool IsEnabled { get; set; }
public bool IsLocked { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime LockedAt { get; set; }
}
And I am using it like this:
User user1 = new User();
user1.Email = "testDev#gmail.com";
user1.UserName = "dora";
user1.Password = "123456";
var UpObject = new Selector<User>( x => x.UserName, x => x.Password, x => x.Email, x => x.IsEnabled );
Dictionary<string,object> result = UpObject.GetFields(user1);
You can avoid parsing the expressions as string if you instead parse them as System.Linq.Expressions.
Full code sample follows, but not exactly for your code, I used DateTime instead of the generic T, adapting should just be find&replace:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace ExprTest
{
class Program
{
static void Main(string[] args)
{
#region Usage
Expression<Func<DateTime, object>> propertySelector = x => x.Day;
Expression<Func<DateTime, object>> methodSelector = x => x.AddDays(1.5);
Expression[] inputSelectors = new Expression[] { propertySelector, methodSelector };
#endregion
//These are your final Selectors
Dictionary<string, Func<DateTime, object>> outputSelectors = new Dictionary<string, Func<DateTime, object>>();
//This would be in your Selector<T> constructor, replace DateTime with T.
//Instead of CleanNamesUp you would decide which part to use by extracting the appropriate Expression argument's Name.
foreach (Expression<Func<DateTime, object>> selectorLambda in inputSelectors)
{
Expression selectorExpression = selectorLambda.Body;
string name = null;
while (string.IsNullOrEmpty(name))
{
switch (selectorExpression)
{
#region Refine expression
//Necessary for value typed arguments, which get boxed by Convert(theStruct, object)
case UnaryExpression unary:
selectorExpression = unary.Operand;
break;
//add other required expression extractions
#endregion
#region Select expression key/name
case MemberExpression fieldOrProperty:
name = fieldOrProperty.Member.Name;
break;
case MethodCallExpression methodCall:
name = methodCall.Method.Name;
break;
//add other supported expressions
#endregion
}
}
outputSelectors.Add(name, selectorLambda.Compile());
}
//Set a breakpoint here to explore the outputSelectors
}
}
}
There could be a library for this, but i don't know about any, except PredicateBuilder for when you need to unify lambda arguments into one lambda expression.
I think maybe you forgot an important keyword 'nameof'. With the keyword, the code will be like this:
class User
{
public string Name { get; set; }
public string Address { get; set; }
public string Tel { get; set; }
}
static Dictionary<string, object> GetFieldsOf<T>(T item, params string[] args)
{
var properties = args.Select(property => typeof(T).GetProperty(property));
return properties.ToDictionary(property => property.Name, property => property.GetValue(item));
}
static void Main(string[] args)
{
var user = new User { Name = "Abel", Address = "Unknown", Tel = "XXX-XXX" };
var result = GetFieldsOf(user, nameof(User.Name), nameof(User.Address));
}
This code will result in some performance problems caused by reflection. But fortunately, you can avoid these by emitting a small segement of code.
//MSIL
ldarg.0
call Property.GetMethod
ret
And replace it with proerpty.GetValue. These code can be generated and cached per type, which is still worthwhile.
I have 2 dictionaries List<Dictionary<string, object>> like this:
[{"Id":"2","FirstName":null,"MiddleName":null,"LastName":null,"Birthday":null,"Username":null,"Password":null,"LastLogin":null,"CreateDateTime":null,"UpdateDateTime":null,"Blocked":null,"HasOrders":null}]
and have a Dictionary like this Dictionary<string, string> for filter
var dict = new Dictionary<string, object>
{
{ "Username", "myUsername" },
{ "Password", "myPassword" }
};
My question is how I can filter out within the first List the records with help of the second list.
Please note that I need a where statement with 2 or 3 dynamic keys/values in the second list. There are a lot of records in these JSON structures.
It be great if somebody can point me to the right direction.
--UPDATE--
something like as I want to have, but than without the foreach:
foreach(Dictionary<string, object> v in Data)
{
v.Where(x =>
x.Key.Contains(nList.Where(n => n.Key == x.Key && n.Value = x.Value)));
}
I have no idea on how todo this in LINQ
I suggest you do this in couple of steps. First step, obviously would be to convert the List> structure to a List. Handling it as Collection of Dictionary is not a good approach.
public class UserPass
{
public string Username{get;set;}
public string Password{get;set;}
}
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public DateTime? Birthday { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public DateTime? LastLogin { get; set; }
public DateTime? CreateDateTime { get; set; }
public DateTime? UpdateDateTime { get; set; }
public bool? Blocked { get; set; }
public bool? HasOrders { get; set; }
}
For example,
var dictionary1 = new Dictionary<string,object>()
{
["Id"]="2",
["FirstName"]=null,
["MiddleName"]=null,
["LastName"]=null,
["Birthday"]=null,
["Username"]="anuviswan",
["Password"]="password",
["LastLogin"]=null,
["CreateDateTime"]=null,
["UpdateDateTime"]=null,
["Blocked"]=null,
["HasOrders"]=null
};
var dictionary2 = new Dictionary<string,object>()
{
["Id"]="3",
["FirstName"]=null,
["MiddleName"]=null,
["LastName"]=null,
["Birthday"]=null,
["Username"]="user1",
["Password"]=null,
["LastLogin"]=null,
["CreateDateTime"]=null,
["UpdateDateTime"]=null,
["Blocked"]=null,
["HasOrders"]=null
};
var dataList= new List<Dictionary<string,object>>
{
dictionary1,dictionary2
};
var dict1 = new Dictionary<string, object>
{
{ "Username", "myUsername" },
{ "Password", "myPassword" }
};
var dict2 = new Dictionary<string, object>
{
{ "Username", "anuviswan" },
{ "Password", "password" }
};
var filterList = new List<Dictionary<string,object>> {dict1, dict2};
var dataObjectList = dataList.Select(x=> new User
{
Id = Convert.ToInt32(x[nameof(User.Id)]),
Username = Convert.ToString(x[nameof(User.Username)]),
Password = Convert.ToString(x[nameof(User.Password)]),
});
var filterObjectList = filterList.Select(x=>
new UserPass
{
Username = Convert.ToString(x[nameof(UserPass.Username)]),
Password = Convert.ToString(x[nameof(UserPass.Password)]),
});
With the new Lists in place, you can query as
var result =dataObjectList.Join(filterObjectList,
d=>d.Username,
f=>f.Username,
(x,y)=> new
{
Data = x,
Filter=y
})
.Where(x=>x.Data.Username.Equals(x.Filter.Username)
&& x.Data.Password.Equals(x.Filter.Password))
.Select(x=>x.Data);;
This IDictionary<string, object> contains user data I'm logging into mongodb. The issue is the TValue is a complex object. The TKey is simply the class name.
For example:
public class UserData
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Admin NewAdmin { get; set; }
}
public class Admin
{
public string UserName { get; set; }
public string Password { get; set; }
}
Currently, I'm trying to iterate through the Dictionary and compare types but to no avail. Is there a better way of doing this or am I missing the mark?
var argList = new List<object>();
foreach(KeyValuePair<string, object> kvp in context.ActionArguments)
{
dynamic v = kvp.Value;
//..compare types...
}
Just use OfType<>(). You don't even need the key.
public static void Main()
{
var d = new Dictionary<string,object>
{
{ "string", "Foo" },
{ "int", 123 },
{ "MyComplexType", new MyComplexType { Text = "Bar" } }
};
var s = d.Values.OfType<string>().Single();
var i = d.Values.OfType<int>().Single();
var o = d.Values.OfType<MyComplexType>().Single();
Console.WriteLine(s);
Console.WriteLine(i);
Console.WriteLine(o.Text);
}
Output:
Foo
123
Bar
Link to Fiddle
I trying to get the id and email list from the JSON. How can i achieve this?
My JSON string is
{
"name":"name1",
"username":"name1",
"id":505,
"state":"active",
"email":"name1#mail.com",
},
{
"name":"name2",
"username":"name2",
"id":504,
"state":"active",
"email":"name2#mail.com",
}
My code is
Dictionary<string, string> engineers = new Dictionary<string, string>();
using (StreamReader r = new StreamReader(#"D:\project\Gitlap\EngineerEmail\jsonlist5.json"))
{
using (JsonTextReader reader = new JsonTextReader(r))
{
JObject o2 = (JObject)JToken.ReadFrom(reader);
string id = o2["id"].ToString();
string email = o2["email"].ToString();
engineers.Add(email, id);
}
}
class UserItems
{
public string id { get; set; }
public string email { get; set; }
}
I can able to get the first person`s mail ID and ID details. I need to iterate this JSON and get all the mail ID and ID.
I don`t know that how to iterate this JSON. I tried some method from the internet but that was not succeeded.
How can I do?
First thing is your JSON input is not valid json, you need to fix it. There are two issues in it. Its not collection of json objects and comma is missing between two objects.
Valid json should look like below.
[{
"name":"name1",
"username":"name1",
"id":505,
"state":"active",
"email":"name1#mail.com",
},
{
"name":"name2",
"username":"name2",
"id":504,
"state":"active",
"email":"name2#mail.com",
}]
Now define a c# class representing your json object.
public class User
{
public string name { get; set; }
public string username { get; set; }
public int id { get; set; }
public string state { get; set; }
public string email { get; set; }
}
Use JSON.Net library to deserialize it as shown below.
private void button1_Click(object sender, EventArgs e)
{
if(File.Exists("json1.json"))
{
string inputJSON = File.ReadAllText("json1.json");
if(!string.IsNullOrWhiteSpace(inputJSON))
{
var userList = JsonConvert.DeserializeObject<List<User>>(inputJSON);
}
}
}
JObject o2 = (JObject)JToken.ReadFrom(reader);
foreach(var obj in o2)
{
string id = obj["id"].ToString();
string Email= obj["Email"].ToString();
engineers.Add(email, id);
}
I would recommend using the Json.NET NuGet package to accomplish this.
Firstly, create a model to represent your JSON data. Typically I would capitalize the first letter of the property names here, but to keep it consistent with the JSON, they are lower case.
public class UserData
{
public string name { get; set; }
public string username { get; set; }
public int id { get; set; }
public string state { get; set; }
public string email { get; set; }
}
You will need to add a using for Json.NET
using Newtonsoft.Json;
Finally, you can load, and deserialize your data into a strongly typed list, which you can then use to populate your engineers dictionary.
string datapath = #"D:\project\Gitlap\EngineerEmail\jsonlist5.json";
Dictionary<string, string> engineers = new Dictionary<string, string>();
List<UserData> data = new List<UserData>();
using (StreamReader r = new StreamReader(datapath))
{
string json = r.ReadToEnd();
data = JsonConvert.DeserializeObject<List<UserData>>(json);
data.ForEach(engineer => engineers.Add(engineer.email, engineer.id.ToString()));
}
As mentioned in another answer, your JSON is also badly formed. This will need correcting before it will deserialize correctly. We just need to add a comma to separate the two objects, and wrap them both in a JSON array, with []
[
{
"name":"name1",
"username":"name1",
"id":505,
"state":"active",
"email":"name1#mail.com"
},
{
"name":"name2",
"username":"name2",
"id":504,
"state":"active",
"email":"name2#mail.com"
}
]
Improvements
As your Id field is an integer, it would be better to change your dictionary from
Dictionary<string, string> engineers = new Dictionary<string, string>();
into
Dictionary<string, int> engineers = new Dictionary<int, string>();
You will then be able to simplify your ForEach query slightly. The ForEach can also be moved outside of the using() block.
data.ForEach(engineer =>
engineers.Add(engineer.email, engineer.id));
Improved solution
This includes the improvements above, I've used var for brevity.
var datapath = #"D:\project\Gitlap\EngineerEmail\jsonlist5.json";
var engineers = new Dictionary<string, int>();
var data = new List<UserData>();
using (var r = new StreamReader(datapath))
{
var json = r.ReadToEnd();
data = JsonConvert.DeserializeObject<List<UserData>>(json);
}
data.ForEach(engineer =>
engineers.Add(engineer.email, engineer.id));
try to create class that represent the data in json object for example
Class obj
{
public int Id { get ; set; }
public string email { get ; set; }
public string username { get ; set; }
public string state { get ; set; }
public string email { get ; set; }
}
then
using System.Web.Script.Serialization;
var js = new JavaScriptSerializer();
List<obj> list = js.Deserialize<List<obj>>(jsonString);
after that you can access all list items id and email by using foreach
I am calling Bloomberg Server API (for Stock Market Data) and getting Data back in a Dictionary<string, object> Where the Key to the dictionary is the Field Name on Bloomberg's side, and the object contains the data value from Bloomberg and can be string, decimal, DateTime, boolean etc.
After I get the Bloomberg Data, I need to populate my strong type entities / classes with the values returned. Depending on what Field Names I send in my request to bloomberg, the returned Dictionary could have different key values. The problem I am having is, the bloomberg field name and my .net entity's property names don't match, so I am not sure I can do this mapping using AutoMapper or a similar library.
I also tried using a Tuple<string,string,object> where the 1st tuple item is the bloomberg field name, the 2nd tuple item is my entity's property name and the 3rd tuple item is the data value returned from bloomberg. That is not working out either (so far), so I am wondering if there is a simple straight-forward way of maintaining this bloombergfield<-->EntityProperty mapping and populate the Entity's value using the Bloomberg Data Value for the respective field. A Generic (i.e. using C# Generics) solution would be even better!
I have pasted below sample console app code so you can paste it and try it out. The 2 dictionaries, 1 for stockdata and other for bonddata have fake data, but you get the idea. I have also added comments below to re-iterate what I am trying to accomplish.
Thanks!!
namespace MapBBFieldsToEntityProperties
{
using System;
using System.Collections.Generic;
class Program
{
public class StockDataResult
{
public string Name { get; set; }
public decimal LastPrice { get; set; }
public DateTime SettlementDate { get; set; }
public decimal EPS { get; set; }
}
public class BondDataResult
{
public string Name { get; set; }
public string Issuer { get; set; }
public decimal Duration { get; set; }
public DateTime YieldToMaturity { get; set; }
}
static void Main(string[] args)
{
// Data Coming from Bloomberg.
// Dictionary Key is the Bloomberg Data Field Name.
// Dictionary Object is the Value returns and can be any .Net primitive Type
// Sample Data returned for a Stock Query to Bloomberg
Dictionary<string, object> dctBloombergStockData
= new Dictionary<string, object>
{
{ "NAME", "IBM" },
{ "PX_LAST", 181.30f },
{ "SETTLE_DT", "11/25/2013" } // This is Datetime value
};
// Sample Data returned for a Bond Query to Bloomberg
Dictionary<string, object> dctBloombergBondData =
new Dictionary<string, object>
{
{ "NAME", "IBM" },
{ "ISSUE_ORG","IBM Corp" },
{ "DURATION", 4.430f },
{ "YLD_TO_M", 6.456f }
};
// This is my Stock Entity
StockDataResult stockData = new StockDataResult();
// This is my Bond Entity
BondDataResult bondData = new BondDataResult();
// PROBLEM STATEMENT:
//
// Need to somehow Map the Data returned from Bloomberg into the
// Corresponding Strong-typed Entity for that Data Type.
// i.e.
// map dctBloombergStockData to stockData Entity instance as follows
//
// dctBloombergStockData."NAME" Key <--------> stockData.Name Property so that
// dctBloombergStockData["NAME"] value of "IBM" can be assigned to stockData.Name
//
// dctBloombergStockData."PX_LAST" Key <--------> stockData.LastPrice Property so that
// dctBloombergStockData["PX_LAST"] value 181.30f can be assigned to stockData.LastPrice value.
// ....
// .. you get the idea.
// Similarly,
// map dctBloombergBondData Data to bondData Entity instance as follows
//
// dctBloombergBondData."NAME" Key <--------> bondData.Name Property so that
// dctBloombergBondData["NAME"] value of "IBM" can be assigned to bondData.Name property's value
//
// dctBloombergBondData."ISSUE_ORG" Key <--------> bondData.Issuer Property so that
// dctBloombergBondData["ISSUE_ORG"] value 181.30f can be assigned to bondData.Issuer property's value.
//
// dctBloombergBondData."YLD_TO_M" Key <--------> bondData.YieldToMaturity Property so that
// dctBloombergBondData["YLD_TO_M"] value 181.30f can be assigned to bondData.YieldToMaturity property's value.
}
}
}
I am sure quite a few improvements are possible, but this is one way of specifying a mapping and using that map.
class Program
{
public class Mapper<TEntity> where TEntity : class
{
private readonly Dictionary<string, Action<TEntity, object>> _propertyMappers = new Dictionary<string, Action<TEntity, object>>();
private Func<TEntity> _entityFactory;
public Mapper<TEntity> ConstructUsing(Func<TEntity> entityFactory)
{
_entityFactory = entityFactory;
return this;
}
public Mapper<TEntity> Map<TProperty>(Expression<Func<TEntity, TProperty>> memberExpression, string bloombergFieldName, Expression<Func<object, TProperty>> converter)
{
var converterInput = Expression.Parameter(typeof(object), "converterInput");
var invokeConverter = Expression.Invoke(converter, converterInput);
var assign = Expression.Assign(memberExpression.Body, invokeConverter);
var mapAction = Expression.Lambda<Action<TEntity, object>>(
assign, memberExpression.Parameters[0], converterInput).Compile();
_propertyMappers[bloombergFieldName] = mapAction;
return this;
}
public TEntity MapFrom(Dictionary<string, object> bloombergDict)
{
var instance = _entityFactory();
foreach (var entry in bloombergDict)
{
_propertyMappers[entry.Key](instance, entry.Value);
}
return instance;
}
}
public class StockDataResult
{
public string Name { get; set; }
public decimal LastPrice { get; set; }
public DateTime SettlementDate { get; set; }
public decimal EPS { get; set; }
}
public static void Main(params string[] args)
{
var mapper = new Mapper<StockDataResult>()
.ConstructUsing(() => new StockDataResult())
.Map(x => x.Name, "NAME", p => (string)p)
.Map(x => x.LastPrice, "PX_LAST", p => Convert.ToDecimal((float)p))
.Map(x => x.SettlementDate, "SETTLE_DT", p => DateTime.ParseExact((string)p, "MM/dd/yyyy", null));
var dctBloombergStockData = new Dictionary<string, object>
{
{ "NAME", "IBM" },
{ "PX_LAST", 181.30f },
{ "SETTLE_DT", "11/25/2013" } // This is Datetime value
};
var myStockResult = mapper.MapFrom(dctBloombergStockData);
Console.WriteLine(myStockResult.Name);
Console.WriteLine(myStockResult.LastPrice);
Console.WriteLine(myStockResult.SettlementDate);
}
}
As you have said your self you need a mapping table. You can create a static read only dictionary in you type that would map each key filed returned from Bloomberg to property in your strongly typed class.
Here is how I would do it.
PS: I used linqpad to test.
PPS: You can add as many mapper(s) to the dictionary as need be. You also need fast-member to run this code.
void Main()
{
var dctBloombergStockData = new Dictionary<string, object>
{
{ "NAME", "IBM" },
{ "PX_LAST", 181.30f },
{ "SETTLE_DT", "11/25/2013" } // This is Datetime value
};
StockDataResult.FromBloombergData(dctBloombergStockData);
}
// Define other methods and classes here
interface IMapper
{
string PropertyName { get; }
object Parse(object source);
}
class Mapper<T, TResult> : IMapper
{
private Func<T, TResult> _parser;
public Mapper(string propertyName, Func<T, TResult> parser)
{
PropertyName = propertyName;
_parser = parser;
}
public string PropertyName { get; private set; }
public TResult Parse(T source)
{
source.Dump();
return _parser(source);
}
object IMapper.Parse(object source)
{
source.Dump();
return Parse((T)source);
}
}
public class StockDataResult
{
private static TypeAccessor Accessor = TypeAccessor.Create(typeof(StockDataResult));
private static readonly Dictionary<string, IMapper> Mappers = new Dictionary<string, IMapper>(StringComparer.CurrentCultureIgnoreCase){
{ "NAME", new Mapper<string, string>("Name", a => a) },
{ "PX_LAST", new Mapper<float, decimal>("LastPrice", a => Convert.ToDecimal(a)) },
{ "SETTLE_DT", new Mapper<string, DateTime>("SettlementDate", a => DateTime.ParseExact(a, "MM/dd/yyyy", null)) }
};
protected StockDataResult()
{ }
public string Name { get; set; }
public float LastPrice { get; set; }
public DateTime SettlementDate { get; set; }
public decimal EPS { get; set; }
public static StockDataResult FromBloombergData(Dictionary<string, object> state)
{
var result = new StockDataResult();
IMapper mapper;
foreach (var entry in state)
{
if(!Mappers.TryGetValue(entry.Key, out mapper))
{ continue; }
Accessor[result, mapper.PropertyName.Dump()] = mapper.Parse(entry.Value);
}
return result;
}
}
How about:
stockData.Name = dctBloombergStockData["NAME"];
stockData.LastPrice = dctBloombergStockData["PX_LAST"]
//and so on...