请考虑以下代码:
public KeyAttribute : Attribute{
public string Value;
public KeyAttribute(string value){
Value = value;
}
}
[Key("A")]
[Key("AB")]
public class A : IClass
{
public string FieldA {get;set;}
}
[Key("B")]
public class B : IClass
{
public string FieldB {get;set;}
}
所以我必须完成IClass
接口的所有实现,并且我必须构建一个字典Dictionary<string, ConstructorInfo>
,其中键是Value
KeyAttribute
属性,值是相应的ConstructorInfo
请注意,单个类可能有多个KeyAttribute
,因此对于这种情况,字典中应该有相应数量的条目。
对于当前示例,期望的结果是:
key | value
--------+-------------------
"A" | ConstructorInfo A
"AB" | ConstructorInfo A
"B" | ConstructorInfo B
起初我写了这个:
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(t => typeof(IClass).IsAssignableFrom(t))
.ToDictionary(t =>
{
var key = (KeyAttribute) t.GetCustomAttributes(typeof(KeyAttribute), true).First();
return key.Value;
}, t => t.GetConstructors(BindingFlags.Public).First());
但正如您所看到的,上面的代码不能处理具有多个属性的情况。 所以我做了以下,但这显然是错误的,我不知道如何纠正它。
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(t => typeof(IClass).IsAssignableFrom(t))
.ToDictionary(t =>
{
return t.GetCustomAttributes(typeof(KeyAttribute), true).Select(a => ((KeyAttribute)a).Value);
}, t => t.GetConstructors(BindingFlags.Public).First());
我知道我可以在没有LINQ的情况下做到这一点:
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(t => typeof(IClass).IsAssignableFrom(t));
var dict = new Dictionary<string, ConstructorInfo>();
foreach (var type in types)
{
var keys = type.GetCustomAttributes(typeof(KeyAttribute), true).Cast<KeyAttribute>().Select(a => a.Value);
var ctorInfo = type.GetConstructors(BindingFlags.Public).First();
foreach (var key in keys)
{
dict.Add(key, ctorInfo);
}
}
return dict;
但如果有可能的话,我宁愿坚持使用LINQ。
对于有关属性的所有这些有些误导性的细节以及所有这些,感到抱歉,虽然它是关于LINQ的问题,但我想不出任何其他生动的例子。
答案 0 :(得分:3)
这应该有效:
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(t => typeof(IClass).IsAssignableFrom(t))
.SelectMany(t => t.GetCustomAttributes(typeof(KeyAttribute), true)
.Select(a => new
{
constInfo = t.GetConstructors(BindingFlags.Public).First(),
attrVal = ((KeyAttribute)a).Value
}))
.ToDictionary(entry => entry.attrVal, entry => entry.constInfo);
答案 1 :(得分:1)
将SelectMany
用于关键属性
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(t => typeof(IClass).IsAssignableFrom(t))
.SelectMany(t =>
{
return t.GetCustomAttributes<KeyAttribute>()
.Select(ka => new
{
Key = ka,
Ctor = t.GetConstructors(BindingFlags.Public).First()
});
})
.ToDictionary(t => t.Key, t.Ctor);