C# LINQ to dictionary具有针对单个值的多个键

C# LINQ to dictionary具有针对单个值的多个键,c#,linq,dictionary,C#,Linq,Dictionary,考虑以下代码: 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

考虑以下代码:

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
,其中键是
KeyAttribute
Value
属性,值是相应的
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;
var types=AppDomain.CurrentDomain.getAssemblys()
.SelectMany(s=>s.GetTypes())
其中(t=>typeof(IClass).IsAssignableFrom(t));
var dict=新字典();
foreach(类型中的变量类型)
{
var keys=type.GetCustomAttributes(typeof(KeyAttribute),true).Cast().Select(a=>a.Value);
var ctorInfo=type.GetConstructors(BindingFlags.Public).First();
foreach(var键入键)
{
dict.Add(键、信息);
}
}
返回命令;
但如果可能的话,我宁愿选择林克

很抱歉,关于属性和所有这些有点误导性的细节,虽然这是一个关于LINQ的问题,但我想不出任何其他生动的例子。

这应该可以:

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);
这应该起作用:

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);

对关键属性使用
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);
返回AppDomain.CurrentDomain.getAssemblys()
.SelectMany(s=>s.GetTypes())
.Where(t=>typeof(IClass).IsAssignableFrom(t))
.SelectMany(t=>
{
返回t.GetCustomAttributes()
.选择(ka=>new
{
Key=ka,
Ctor=t.GetConstructors(BindingFlags.Public).First()
});
}) 
.ToDictionary(t=>t.Key,t.Ctor);

使用
选择多个
作为关键属性

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);
返回AppDomain.CurrentDomain.getAssemblys()
.SelectMany(s=>s.GetTypes())
.Where(t=>typeof(IClass).IsAssignableFrom(t))
.SelectMany(t=>
{
返回t.GetCustomAttributes()
.选择(ka=>new
{
Key=ka,
Ctor=t.GetConstructors(BindingFlags.Public).First()
});
}) 
.ToDictionary(t=>t.Key,t.Ctor);

嘿,谢谢你的回答!答案有点问题-第一个
Select
实际上应该是
SelectMany
。否则,我们必须处理
IEnumerable
而不是
IEnumerable
。嘿,谢谢你的回答!答案有点问题-第一个
Select
实际上应该是
SelectMany
。否则,我们必须处理
IEnumerable
,而不是
IEnumerable