我有 2 个通用列表List<type1> L1
,List<type2> L2
在 C# V4 中
我的问题:type1 有一个名为“key1”的属性,type2 有一个名为“key2”的属性,我想将 L1 和 L2 合并到 key1 = key2 上的唯一列表中。
我需要用动态的方式合并这些,因为我不知道这两个类的属性,我只知道每个类型的第一个属性是主键。
var foo = (from type1 in list1
join type2 in list2 on type1.Id equals type2.Id
select new {type1, type2}).ToList();
通过说“属性”,我假设您正在引用属性或字段。请不要使用“属性”,因为这令人困惑并且意味着完全不同的东西:
[Attribute]
class type1
{
public int Field;
public int Property { get; set; }
}
因此,您有 type1 和 type2,并希望根据类中的第一个字段或属性将它们加入一个列表。如果您知道属性名称,最简单的实现是使用动态(假设 Prop1 和 Prop2 属性名称):
var foo =
(from type1 in list1
join type2 in list2 on ((dynamic)type1).Prop1 equals ((dynamic)type2).Prop2
select new {type1, type2}).ToList();
由于情况并非如此,我们想在类中选择“第一个”字段或属性,我们唯一的方法是使用反射。如果您知道您的类中只有属性(或只有字段) - 您可以使用简单的实现:
var t1 = typeof(type1);
var t2 = typeof(type2);
//replace with .GetFields() if neccessary
var p1 = t1.GetProperties()[0]; // find first declared property of type1
var p2 = t2.GetProperties()[0]; // find first declared property of type2
var foo = (from obj1 in list1
join obj2 in list2 on p1.GetValue(obj1,null) equals p2.GetValue(obj2,null)
select new {obj1, obj2}).ToList();
如果您的类中混合了字段和属性,您可以使用FindMembers(MemberTypes.Field|MemberTypes.Property...)列出所有成员,但是这种方法有一个问题 - 字段总是重新定位到类的开头,尽管字段似乎保留了顺序,在以下情况下,F1 将始终作为类的第一个成员返回(GetFields() 将返回 F1、F2 和 GetProperties - P1、this[]):
class A
{
public int P1 { get;set;}
public int F1;
public int this[int x] { get{return x;} set {} }
public int F2;
}
此外,这种方法还有其他问题:
通常,这种设计(当您不知道字段/属性名称,并且依赖于它们在类中的相对位置时)被认为是不好的。引用MSDN: ... GetMembers 方法不按特定顺序返回成员,例如字母顺序或声明顺序。您的代码不得依赖于返回成员的顺序,因为该顺序会有所不同。