C# 如何使用Linq中的泛型接口类型进行过滤?

C# 如何使用Linq中的泛型接口类型进行过滤?,c#,linq,generics,C#,Linq,Generics,我需要在列表中处理通用接口的所有变体 在下面的示例中,有DerivedPerson,每个都保存对其PersonTemplate的引用 internal interface ITemplate { int TemplateID { get; set; } } internal class PersonTemplate : ITemplate { public PersonTemplate(int templateId) { TemplateID = tem

我需要在列表中处理通用接口的所有变体

在下面的示例中,有
DerivedPerson
,每个都保存对其
PersonTemplate
的引用

internal interface ITemplate
{
    int TemplateID { get; set; }
}

internal class PersonTemplate : ITemplate
{
    public PersonTemplate(int templateId)
    {
        TemplateID = templateId;
    }

    public int TemplateID { get; set; }
}

internal interface ITemplateInstance<TTemplate> where TTemplate : ITemplate
{
    TTemplate TemplateReference { get; set; }
}

internal class DerivedPerson : ITemplateInstance<PersonTemplate>
{
    public DerivedPerson(PersonTemplate template)
    {
        TemplateReference = template;
    }

    public PersonTemplate TemplateReference { get; set; }
}

internal class Program
{
    private static void Main(string[] args)
    {
        IList<object> objects = new List<object>
        {
            new object(),
            new DerivedPerson(new PersonTemplate(1)),
            new DerivedPerson(new PersonTemplate(2))
        };

        //Count = 2
        List<ITemplate> personTemplates = objects
                                            .OfType<ITemplateInstance<PersonTemplate>>()
                                            .Select(pi => pi.TemplateReference as ITemplate)
                                            .ToList();

        //Count = 0 (!)
        List<ITemplate> allTemplates = objects
                                            .OfType<ITemplateInstance<ITemplate>>()
                                            .Select(pi => pi.TemplateReference)
                                            .ToList();
    }
}
内部接口项目板
{
int TemplateID{get;set;}
}
内部类PersonTemplate:ITemplate
{
公共PersonTemplate(int templateId)
{
TemplateID=TemplateID;
}
public int TemplateID{get;set;}
}
内部接口ITemplate实例,其中TTemplate:ITemplate
{
tTemplateTemplateReference{get;set;}
}
内部类DerivedPerson:ITemplateInstance
{
公共派生人员(PersonTemplate模板)
{
TemplateReference=模板;
}
public PersonTemplate TemplateReference{get;set;}
}
内部课程计划
{
私有静态void Main(字符串[]args)
{
IList对象=新列表
{
新对象(),
新衍生人员(新员工(1)),
新衍生人员(新员工(2))
};
//计数=2
List personTemplates=对象
第()类
.选择(pi=>pi.TemplateReference作为ITemplate)
.ToList();
//计数=0(!)
列出所有模板=对象
第()类
.Select(pi=>pi.templaterReference)
.ToList();
}
}
Main
方法中,我希望处理任何模板的所有实例,而不仅仅是
PersonTemplate类型的实例。我正在寻找一种通用的方法来处理这个问题

我发现了一个类似的、已经被接受的问题。但我的目标不是继续使用过滤后的
IList
,而是使用
IList

,您可以使用:

List<ITemplate> allTemplates
              = objects.Where(o => o.GetType()                                                                              
                                    .GetInterfaces()
                                    .Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ITemplateInstance<>)))
                       .Select(o => o.GetType()
                                     .GetProperty("TemplateReference")
                                     .GetValue(o))
                       .OfType<ITemplate>()
                       .ToList();
列出所有模板
=对象。其中(o=>o.GetType()
.GetInterfaces()
.Any(i=>i.IsGenericType&&i.GetGenericTypeDefinition()==typeof(ITemplateInstance)))
.Select(o=>o.GetType()
.GetProperty(“TemplateReference”)
.GetValue(o))
第()类
.ToList();

一个
ITemplateInstance
根本不是一个
ITemplateInstance>
——例如,你将无法从一个转换到另一个。如果
templaterreference
为只读,则可以声明
ITemplateReference
,这将起作用。。。这对您来说足够好吗?OfType查看实例类型并返回一个可以转换为该类型的实例集合。我们不能强制转换到接口(如ITemplateInstance)@乔恩:那将是更好的解决办法。然而,我的代码需要大量重构以允许协变here@mamuesstack:在这种情况下,您会遇到一个问题,因为类型根本不兼容。你可以创建一个非通用的基本接口,但这无助于你跳出
模板引用
:(你是什么意思?它完全符合他的要求。它是用来替换他的“
列出所有模板
…”行。我的错…我没有看到问题的底部。对不起?!