大家好,感谢您的光临。
我不认为这是可能的,但我想通过多个返回的LIST<>来做同样的FOREACH。类型,无需剪切和粘贴代码4次。返回的dto2,dto3,dto4和dto5列表的所有属性都是相同的,除了DataValue,它是每个(int,varchar,bool等)的不同数据类型
var dto2 = rd.EngDetailBitsList(dto.EngId);
var dto3 = rd.EngDetailDateTimesList(dto.EngId);
var dto4 = rd.EngDetailVarCharsList(dto.EngId);
var dto5 = rd.EngDetailVarCharMaxesList(dto.EngId);
foreach (var x in dto2)
{
var propertyInfo = dto.GetType().GetProperty(x.ShortDescript,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (propertyInfo != null)
{
propertyInfo.SetValue(dto, x.DataValue);
}
}
foreach (var x in dto3)
{
var propertyInfo = dto.GetType().GetProperty(x.ShortDescript,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (propertyInfo != null)
{
propertyInfo.SetValue(dto, x.DataValue);
}
}
foreach (var x in dto4)
{
var propertyInfo = dto.GetType().GetProperty(x.ShortDescript,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (propertyInfo != null)
{
propertyInfo.SetValue(dto, x.DataValue);
}
}
foreach (var x in dto5)
{
var propertyInfo = dto.GetType().GetProperty(x.ShortDescript,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (propertyInfo != null)
{
propertyInfo.SetValue(dto, x.DataValue);
}
}
答案 0 :(得分:2)
有两种解决方法:
假设所有dto2
,dto3
,dto4
和dto5
都是某种类型T
的集合,它们与{{1}实现了通用接口在其上声明了ShortDescript
属性。
DataValue
如果没有通用界面,您可以使用var dto2 = rd.EngDetailBitsList(dto.EngId);
var dto3 = rd.EngDetailDateTimesList(dto.EngId);
var dto4 = rd.EngDetailVarCharsList(dto.EngId);
var dto5 = rd.EngDetailVarCharMaxesList(dto.EngId);
var source = dto2.Cast<MyInterface>
.Concat(dto3.Cast<MyInterface>)
.Concat(dto4.Cast<MyInterface>)
.Concat(dto4.Cast<MyInterface>);
var dtoType = dto.GetType();
foreach (var x in source)
{
var propertyInfo = dtoType.GetProperty(x.ShortDescript,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (propertyInfo != null)
{
propertyInfo.SetValue(dto, x.DataValue);
}
}
:
dynamic
这将使var dto2 = rd.EngDetailBitsList(dto.EngId);
var dto3 = rd.EngDetailDateTimesList(dto.EngId);
var dto4 = rd.EngDetailVarCharsList(dto.EngId);
var dto5 = rd.EngDetailVarCharMaxesList(dto.EngId);
var source = dto2.Cast<dynamic>
.Concat(dto3.Cast<dynamic>)
.Concat(dto4.Cast<dynamic>)
.Concat(dto4.Cast<dynamic>);
dto.GetType()
foreach (var x in source)
{
var propertyInfo = dtoType.GetProperty(x.ShortDescript,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (propertyInfo != null)
{
propertyInfo.SetValue(dto, x.DataValue);
}
}
和ShortDescript
属性在运行时得到解析,并且当实际类型上没有这样的属性时,您将获得异常。
答案 1 :(得分:0)
如果你想要一个全反射解决方案,你可以制作一个这样的方法:
static void SetDtoFields<T>(object targetDto, IEnumerable<T> fields)
{
Type fieldType = typeof(T);
var fieldNameProp = fieldType.GetProperty("ShortDescript");
if (fieldNameProp == null || !fieldNameProp.CanRead)
return;
var dataValProp = fieldType.GetProperty("DataValue");
if (dataValProp == null || !dataValProp.CanRead)
return;
Type targetType = targetDto.GetType();
foreach (T field in fields)
{
var propToSet = targetType.GetProperty((string)fieldNameProp.GetValue(field),
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase );
if (propToSet != null && propToSet.CanWrite &&
propToSet.PropertyType.IsAssignableFrom(dataValProp.PropertyType))
{
propToSet.SetValue(targetDto, dataValProp.GetValue(field));
}
}
}
然后在主代码中你可以做到:
SetDtoFields(dto, rd.EngDetailBitsList(dto.EngId));
SetDtoFields(dto, rd.EngDetailDateTimesList(dto.EngId));
SetDtoFields(dto, rd.EngDetailVarCharsList(dto.EngId));
SetDtoFields(dto, rd.EngDetailVarCharMaxesList(dto.EngId));
这是一个有效的演示:https://dotnetfiddle.net/GhrJ0f
答案 2 :(得分:0)
我会尝试这样的事情。对于你的dto2,dto3,dto4,dto5类,让他们分享这个界面:
public interface IDto
{
string ShortDescript {get;set;}
object ObjectValue {get;}
}
在对象上实现ObjectValue(以一个为例):
public partial class DetailBits // dto2 class maybe?
{
public object ObjectValue
{
get
{
return DataValue;
}
}
}
然后,创建此功能:
public static void SetValues(DTO dto, IEnumerable<IDto> items)
{
foreach (var x in items)
{
var propertyInfo = dto.GetType().GetProperty(x.ShortDescript,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (propertyInfo != null)
{
propertyInfo.SetValue(dto, x.ObjectValue);
}
}
}
最后,您可以在主要功能中执行此操作:
var dto2 = rd.EngDetailBitsList(dto.EngId).Cast<IDto>();
var dto3 = rd.EngDetailDateTimesList(dto.EngId).Cast<IDto>();
var dto4 = rd.EngDetailVarCharsList(dto.EngId).Cast<IDto>();
var dto5 = rd.EngDetailVarCharMaxesList(dto.EngId).Cast<IDto>();
SetValues(dto, dto2);
SetValues(dto, dto3);
SetValues(dto, dto4);
SetValues(dto, dto5);
答案 3 :(得分:0)
我使用了Martin的#2动态强制转换解决方案,并进行了一些编辑更改。工作真棒!
var dto2 = rd.EngDetailBitsList(dto.EngId);
var dto3 = rd.EngDetailDateTimesList(dto.EngId);
var dto4 = rd.EngDetailVarCharsList(dto.EngId);
var dto5 = rd.EngDetailVarCharMaxesList(dto.EngId);
var source = dto2.Concat(dto3.Concat(dto4.Concat(dto5.Cast<dynamic>())));
var dtoType = dto.GetType();
foreach (var x in source)
{
var propertyInfo = dtoType.GetProperty(x.ShortDescript,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (propertyInfo != null)
{
propertyInfo.SetValue(dto, x.DataValue);
}
}
答案 4 :(得分:-1)
你可以试试这个,它的作用就是把你的DTO对象,集合以及要获取和设置的属性名称。
var dto2 = rd.EngDetailBitsList(dto.EngId);
var dto3 = rd.EngDetailDateTimesList(dto.EngId);
var dto4 = rd.EngDetailVarCharsList(dto.EngId);
var dto5 = rd.EngDetailVarCharMaxesList(dto.EngId);
ObjectSetter(new object() /* test only */, dto2, "DataValue");
private void ObjectSetter(object dto, string dtoProp,
IEnumerable items, string itemProperty)
{
foreach (var item in items)
{
var propertyInfo = item.GetType().GetProperty(dtoProp,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
var itemValue = dto.GetType().GetProperty(itemProperty,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
if (propertyInfo != null)
{
propertyInfo.SetValue(item, itemValue.GetValue(dto));
}
}
}
您可以通过执行异步处理来提高性能。像这样称呼它
Task.Factory.StartNew(delegate()
{
ObjectSetter(new object() /* test only */, dto2, "DataValue");
});
Task.Factory.StartNew(delegate()
{
ObjectSetter(new object() /* test only */, dto3, "DataValue");
});
Task.Factory.StartNew(delegate()
{
ObjectSetter(new object() /* test only */, dto4, "DataValue");
});
Task.Factory.StartNew(delegate()
{
ObjectSetter(new object() /* test only */, dto5, "DataValue");
});