多个LIST上的C#FOREACH<>类型

时间:2014-11-25 02:00:41

标签: c# list foreach

大家好,感谢您的光临。

我不认为这是可能的,但我想通过多个返回的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);
    }
}

5 个答案:

答案 0 :(得分:2)

有两种解决方法:

  1. 假设所有dto2dto3dto4dto5都是某种类型T的集合,它们与{{1}实现了通用接口在其上声明了ShortDescript属性。

    DataValue
  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.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");
        });