62

このクラスがあると考えてください:

    public  class Data
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }
    public string Field3 { get; set; }
    public string Field4 { get; set; }
    public string Field5 { get; set; }

}

特定の列を動的に選択するにはどうすればよいですか? このようなもの :

  var list = new List<Data>();

  var result= list.Select("Field1,Field2"); // How ?

これが唯一の解決策ですか => Dynamic LINQ ですか?
選択されたフィールドは、コンパイル時には不明です。それらは実行時に指定されます

4

11 に答える 11

4

プロパティ値をその名前で取得および設定するには、リフレクションを使用する必要があります。

  var result = new List<Data>();
  var data = new Data();
  var type = data.GetType();
  var fieldName = "Something";

  for (var i = 0; i < list.Count; i++)
  {
      foreach (var property in data.GetType().GetProperties())
      {
         if (property.Name == fieldName)
         {
            type.GetProperties().FirstOrDefault(n => n.Name == property.Name).SetValue(data, GetPropValue(list[i], property.Name), null);
            result.Add(data);
         }
      }
  }

そして、ここに GetPropValue() メソッドがあります

public static object GetPropValue(object src, string propName)
{
   return src.GetType().GetProperty(propName).GetValue(src, null);
}
于 2013-05-13T08:56:05.463 に答える
1

同じ使用目的で独自のクラスを生成しました。

github の要点: https://gist.github.com/mstrYoda/663789375b0df23e2662a53bebaf2c7c

指定された文字列に対して動的選択ラムダを生成し、2 レベルのネストされたプロパティもサポートします。

使用例は次のとおりです。

class Shipment {
   // other fields...
   public Address Sender;
   public Address Recipient;
}

class Address {
    public string AddressText;
    public string CityName;
    public string CityId;
}

// in the service method
var shipmentDtos = _context.Shipments.Where(s => request.ShipmentIdList.Contains(s.Id))
                .Select(new SelectLambdaBuilder<Shipment>().CreateNewStatement(request.Fields)) // request.Fields = "Sender.CityName,Sender.CityId"
                .ToList();

以下のようにラムダをコンパイルします。

s => new Shipment {
    Sender = new Address {
        CityId = s.Sender.CityId,
        CityName = s.Sender.CityName
    }
}

ここで私の質問と回答を見つけることもできます: c# - ネストされたプロパティを使用して linq select を動的に生成する

public class SelectLambdaBuilder<T>
{
// as a performence consideration I cached already computed type-properties
private static Dictionary<Type, PropertyInfo[]> _typePropertyInfoMappings = new Dictionary<Type, PropertyInfo[]>();
private readonly Type _typeOfBaseClass = typeof(T);

private Dictionary<string, List<string>> GetFieldMapping(string fields)
{
    var selectedFieldsMap = new Dictionary<string, List<string>>();

    foreach (var s in fields.Split(','))
    {
        var nestedFields = s.Split('.').Select(f => f.Trim()).ToArray();
        var nestedValue = nestedFields.Length > 1 ? nestedFields[1] : null;

        if (selectedFieldsMap.Keys.Any(key => key == nestedFields[0]))
        {
            selectedFieldsMap[nestedFields[0]].Add(nestedValue);
        }
        else
        {
            selectedFieldsMap.Add(nestedFields[0], new List<string> { nestedValue });
        }
    }

    return selectedFieldsMap;
}

public Func<T, T> CreateNewStatement(string fields)
{
    ParameterExpression xParameter = Expression.Parameter(_typeOfBaseClass, "s");
    NewExpression xNew = Expression.New(_typeOfBaseClass);

    var selectFields = GetFieldMapping(fields);

    var shpNestedPropertyBindings = new List<MemberAssignment>();
    foreach (var keyValuePair in selectFields)
    {
        PropertyInfo[] propertyInfos;
        if (!_typePropertyInfoMappings.TryGetValue(_typeOfBaseClass, out propertyInfos))
        {
            var properties = _typeOfBaseClass.GetProperties();
            propertyInfos = properties;
            _typePropertyInfoMappings.Add(_typeOfBaseClass, properties);
        }

        var propertyType = propertyInfos
            .FirstOrDefault(p => p.Name.ToLowerInvariant().Equals(keyValuePair.Key.ToLowerInvariant()))
            .PropertyType;

        if (propertyType.IsClass)
        {
            PropertyInfo objClassPropInfo = _typeOfBaseClass.GetProperty(keyValuePair.Key);
            MemberExpression objNestedMemberExpression = Expression.Property(xParameter, objClassPropInfo);

            NewExpression innerObjNew = Expression.New(propertyType);

            var nestedBindings = keyValuePair.Value.Select(v =>
            {
                PropertyInfo nestedObjPropInfo = propertyType.GetProperty(v);

                MemberExpression nestedOrigin2 = Expression.Property(objNestedMemberExpression, nestedObjPropInfo);
                var binding2 = Expression.Bind(nestedObjPropInfo, nestedOrigin2);

                return binding2;
            });

            MemberInitExpression nestedInit = Expression.MemberInit(innerObjNew, nestedBindings);
            shpNestedPropertyBindings.Add(Expression.Bind(objClassPropInfo, nestedInit));
        }
        else
        {
            Expression mbr = xParameter;
            mbr = Expression.PropertyOrField(mbr, keyValuePair.Key);

            PropertyInfo mi = _typeOfBaseClass.GetProperty( ((MemberExpression)mbr).Member.Name );

            var xOriginal = Expression.Property(xParameter, mi);

            shpNestedPropertyBindings.Add(Expression.Bind(mi, xOriginal));
        }
    }

    var xInit = Expression.MemberInit(xNew, shpNestedPropertyBindings);
    var lambda = Expression.Lambda<Func<T,T>>( xInit, xParameter );

    return lambda.Compile();
}
于 2018-08-09T12:41:43.347 に答える
-13
var result = from g in list.AsEnumerable()
                select new {F1 = g.Field1,F2  = g.Field2};
于 2013-05-13T07:45:50.940 に答える