我正在调用彭博服务器API(针对股市数据)并将数据恢复到Dictionary<string, object>
,其中字典的Key
是彭博方面的Field Name
,并且该对象包含Bloomberg的数据值,可以是string
,decimal
,DateTime
,boolean
等。
获得Bloomberg数据后,我需要使用返回的值填充强类型实体/类。根据我在对bloomberg的请求中发送的字段名称,返回的字典可以具有不同的键值。我遇到的问题是, bloomberg字段名称和我的.net实体的属性名称不匹配,所以我不确定我是否可以使用AutoMapper
或类似的库进行此映射
我也尝试使用Tuple<string,string,object>
,其中第一个元组项是bloomberg字段名,第二个元组项是我的实体的属性名,第三个元组项是从bloomberg返回的数据值。这也没有成功(到目前为止),所以我想知道是否有一种简单的直接方式来维护这个bloombergfield&lt; - &gt; EntityProperty映射并使用相应字段的Bloomberg数据值填充实体的值。 Generic(即使用C#Generics)解决方案会更好!
我已粘贴下面的示例控制台应用代码,因此您可以将其粘贴并试用。 2个词典,1个用于stockdata
,其他用于bonddata
有假数据,但您明白了。我还在下面添加了评论,以重新尝试我想要完成的任务。
谢谢!
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.
}
}
}
答案 0 :(得分:3)
我确信可以进行一些改进,但这是指定映射和使用该映射的一种方法。
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);
}
}
答案 1 :(得分:1)
正如你所说的那样,你需要一张映射表。您可以在类型中创建一个静态只读字典,它将从Bloomberg返回的每个键字段映射到强类型类中的属性。
我将如何做到这一点。 PS:我用linqpad来测试。 PPS:您可以根据需要在字典中添加任意数量的映射器。您还需要fast-member来运行此代码。
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;
}
}
答案 2 :(得分:-1)
怎么样:
stockData.Name = dctBloombergStockData["NAME"];
stockData.LastPrice = dctBloombergStockData["PX_LAST"]
//and so on...