如何从具有泛型列表的泛型模型中获取属性名称和值? [英] How to get property name and value from generic model with generic list?
问题描述
以以下模型为例.
public class FooModel
{
public FooModel()
{
Bars= new List<BarModel>();
}
[ManyToMany]
public IList<BarModel> Bars{ get; set; }
}
public class BarModel
{
public int Id { get; set; }
}
我需要从fooModel
对象推断List<BarModel>
,并从列表中的每个BarModel建立一个Dictionary<string, object>
.
I need to extrapolate the List<BarModel>
from a fooModel
object, and build up a Dictionary<string, object>
from each BarModel in the list.
假设我创建了以下对象.
Let's say I create the following object.
var fooModel = new FooModel();
var bar1 = new BarModel {Id = 1};
var bar2 = new BarModel {Id = 2};
fooModel.Bars = new List<BarModel>{bar1,bar2};
现在我想获取Foo中所有具有[ManyToMany]
属性的属性.
And now I want to get all properties within Foo that have the [ManyToMany]
attribute.
// First I call the method and pass in the model
DoSomething(fooModel);
// Next I extract some values (used elsewhere)
public DoSomething<TModel>(IModel model){
var dbProvider = ...;
var mapper = new AutoMapper<TModel>();
var tableName = GetTableName( typeof( TModel ) );
UpdateJoins( dbProvider, fooModel, tableName, mapper );
}
// Finally I begin dealing with the collection.
private static void UpdateJoins<TModel> ( IDbProvider dbProvider, TModel model, string tableName, IAutoMapper<TModel> mapper ) where TModel : class, new()
{
foreach (
var collection in
model.GetType()
.GetProperties()
.Where( property => property.GetCustomAttributes( typeof( ManyToManyAttribute ), true ).Any() ) )
{
if ( !IsGenericList( collection.PropertyType ) )
throw new Exception( "The property must be a List" );
// Stuck Here - pseudo code
//====================
foreach (loop the collection)
var collectionName = ...; // Bar
var nestedPropertyName = ...; // Id
var rightKey = collectionName + nestedPropertyName; // BarId
var nestedPropertyValue = ...; // 1
}
}
在上面的示例中,外部foreach
仅将运行一次,因为FooModel
中只有一个用[ManyToMany]
属性修饰的属性.
In the example above, the OUTER foreach
is only going to run ONCE because there is only one Property within FooModel
that is decorated with the [ManyToMany]
attribute.
因此,PropertyInfo property
是List<BarModel>
如何执行上述内部foreach
并提取所需的数据?
How do I do the above INNER foreach
and extract the required data?
推荐答案
这可能会让您步入正轨.这个想法是,如果您遇到[ManyToMany]/泛型列表,则可以通过递归调用相同的方法来反映它,然后将返回的值展平以形成唯一键.您可能需要对其进行调整以适合您的问题.下面的代码返回一个字典,其中包含根据集合名称,索引和属性名称构建的带格式键字符串.例如:
This may get you on the right track. The idea is if you encounter a [ManyToMany] / generic list you reflect it using recursive call to the same method and then flatten the returned values to form a unique key. You probably will need to tweak it to suit your problem. The below code returns a dictionary with formatted key strings built from collection names, indexes and property names. E.G:
Bars[0].Id = 1
Bars[1].Id = 2
代码:
//This is just a generic wrapper for the other Reflect method
private static Dictionary<string, string> Reflect<TModel>(TModel Model)
{
return Reflect(Model.GetType(), Model);
}
private static Dictionary<string, string> Reflect(Type Type, object Object)
{
var result = new Dictionary<string, string>();
var properties = Type.GetProperties();
foreach (var property in properties)
{
if (
property.GetCustomAttributes(typeof(ManyToManyAttribute), true).Any() &&
property.PropertyType.GetGenericTypeDefinition() == typeof(IList<>))
{
var genericType = property.PropertyType.GetGenericArguments().FirstOrDefault();
var listValue = (IEnumerable)property.GetValue(Object, null);
int i = 0;
foreach (var value in listValue)
{
var childResult = Reflect(genericType, value);
foreach (var kvp in childResult)
{
var collectionName = property.Name;
var index = i;
var childPropertyName = kvp.Key;
var childPropertyValue = kvp.Value;
var flattened = string.Format("{0}[{1}].{2}", collectionName, i, childPropertyName);
result.Add(flattened, childPropertyValue);
}
i++;
}
}
else
{
result.Add(property.Name, property.GetValue(Object, null).ToString());
}
}
return result;
}
这篇关于如何从具有泛型列表的泛型模型中获取属性名称和值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!