投放并合并两个相同接口的列表,但不同类型 [英] Cast and merge two lists of same interfaces but different types

查看:129
本文介绍了投放并合并两个相同接口的列表,但不同类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个实体使用相同的界面。我想将我从实体框架获得的两个结果合并到一个 IKules列表

  public async任务< IEnumerable< IKurs< ITeacherToCourse< IAdditionalTeacherData>,IAdditionalTeacherData>>>> GetCourses(bool takeXtr)
{
IEnumerable< IKurs< ITeacherToCourse< IAdditionalTeacherData> IAdditionalTeacherData>> result = new List< IKurs< ITeacherToCourse< IAdditionalTeacherData> IAdditionalTeacherData>>();
if(takeXtr)
using(var context = new Context())
{
var courses = context.XtrCourses.Include(x => x.TeachersToCourses).Where (_someCourseFilterForAgs);
result.Concat(await courses.ToListAsync())。Cast< IKurs< ITeacherToCourse< IAdditionalTeacherData> IAdditionalTeacherData>>();
}

using(var context = new Context())
{
var courses = context.AgsCourses.Include(x => x.TeachersToCourses)凡(_someCourseFilterForAgs);
result.Concat(await courses.ToListAsync())。Cast< IKurs< ITeacherToCourse< IAdditionalTeacherData> IAdditionalTeacherData>>();
}
返回结果;
}

如您所见,我尝试用
.Cast< IKurs< ITeacherToCourse< IAdditionalTeacherData>,IAdditionalTeacherData>>()(抛出InvalidCastException)



课程,既实现 IKurs ,T1> ,但它们的T1和T2是不同的(但仍然使用相同的接口):

  public class XtrCourse:Core_Xtr_Course,IKurs< XtrTeacherToCourse,XtrAdditionalTeacherData> 
{
public int Nr {get;组;
// property

public ICollection< XtrTeacherToCourse> TeachersToCourses {get;组; }
}

public class AgsCourse:Core_Ags_Course,IKurs< AgsTeacherToCourse,AgsAdditionalTeacherData>
{
public int Nr {get;组; }
//属性

public ICollection< AgsTeacherToCourse> TeachersToCourses {get;组; }
}

public interface IKurs< TTeacherToCourse,TAdditionalTeacherData>
其中TTeacherToCourse:ITeacherToCourse< TAdditionalTeacherData>
其中TAdditionalTeacherData:IAdditionalTeacherData
{
int Nr {get;组; }

ICollection< TTeacherToCourse> TeachersToCourses {get;组; }
}

public interface ITeacherToCourse< T>其中T:IAdditionalTeacherData
{
int Nr {get;组; }
T AdditionalTeacherData {get;组; }
}

public interface IAdditionalTeacherData
{
//属性
}

class AgsTeacherToCourse XtrTeacherToCourse 都实现 ITeacherToCourse
class AgsTeacherToCourse XtrTeacherToCourse 都实现 ITeacherToCourse



如何将它们合并到一个列表?



,两个课程列表来自不同的上下文。这就是为什么我在 GetCourses()中启动上下文。

解决方案

p>主要问题之一是

 界面ITeacherToCourse< T>其中T:IAdditionalTeacherData 
{
int Nr {get;组; }
T AdditionalTeacherData {get;组; }
}

class XtrTeacherToCourse:ITeacherToCourse< XtrAdditionalTeacherData>
{
public int Nr {get;组; }
public XtrAdditionalTeacherData AdditionalTeacherData {get;组; }
}

class AgsTeacherToCourse:ITeacherToCourse< AgsAdditionalTeacherData>
{
public int Nr {get;组; }
public AgsAdditionalTeacherData AdditionalTeacherData {get;组; }
}

界面契约定义您只能设置 的值 AdditionalTeacherData 类型 XtrAdditionalTeacherData for XtrAdditionalTeacherData AgsAdditionalTeacherData for AgsTeacherToCourse



我们如何确保当我们能够

  ITeacherToCourse< IAdditionalTeacherData> ttc = new XtrTeacherToCourse(); 
ttc.AdditionalTeacherData = new AgsAdditionalTeacherData();

如果您不想设置 AdditionalTeacherData 属性,则可以声明接口,如

  interface ITeacherToCourse< out T>其中T:IAdditionalTeacherData 
{
int Nr {get;组; }
T AdditionalTeacherData {get; }
}

AdditionalTeacherData 现在只读 T 是一个 out T



现在我们可以

  ITeacherToCourse< IAdditionalTeacherData> TTC; 
ttc = new XtrTeacherToCourse();
ttc = new AgsTeacherToCourse();

与集合相同。



总界面声明

 界面IAdditionalTeacherData 
{

}

接口ITeacherToCourse< out T>其中T:IAdditionalTeacherData
{
int Nr {get;组; }
T AdditionalTeacherData {get; }
}

接口IKurs< out TTeacherToCourse,out TAdditionalTeacherData>
其中TTeacherToCourse:ITeacherToCourse< TAdditionalTeacherData>
其中TAdditionalTeacherData:IAdditionalTeacherData
{
int Nr {get;组; }
IEnumerable< TTeacherToCourse> TeachersToCourses {get; }
}

和实施类

  class XtrAdditionalTeacherData:IAdditionalTeacherData 
{

}

class XtrTeacherToCourse:ITeacherToCourse< XtrAdditionalTeacherData>
{
public int Nr {get;组; }
public XtrAdditionalTeacherData AdditionalTeacherData {get;组; }
}

class XtrCourse:IKurs< XtrTeacherToCourse,XtrAdditionalTeacherData>
{
public int Nr {get;组; }
public ICollection< XtrTeacherToCourse> TeachersToCourses {get;组; }
//显式实现
IEnumerable< XtrTeacherToCourse> IKurs< XtrTeacherToCourse,XtrAdditionalTeacherData> .TeachersToCourses => TeachersToCourses;
}

class AgsAdditionalTeacherData:IAdditionalTeacherData
{

}

class AgsTeacherToCourse:ITeacherToCourse< AgsAdditionalTeacherData>
{
public int Nr {get;组; }
public AgsAdditionalTeacherData AdditionalTeacherData {get;组; }
}

class AgsCourse:IKurs< AgsTeacherToCourse,AgsAdditionalTeacherData>
{
public int Nr {get;组; }
public ICollection< AgsTeacherToCourse> TeachersToCourses {get;组; }
//显式执行
IEnumerable< AgsTeacherToCourse> IKurs< AgsTeacherToCourse,AgsAdditionalTeacherData> .TeachersToCourses => TeachersToCourses;
}

现在我们可以添加没有任何演员的实例

  var collection = new List< IKurs< ITeacherToCourse< IAdditionalTeacherData> IAdditionalTeacherData>>(); 

collection.Add(new XtrCourse());
collection.Add(new AgsCourse());


I got two entities with using same interface. I want to merge both results I get from entity framework to one list of IKurs:

public async Task<IEnumerable<IKurs<ITeacherToCourse<IAdditionalTeacherData>, IAdditionalTeacherData>>> GetCourses(bool takeXtr)
{
    IEnumerable<IKurs<ITeacherToCourse<IAdditionalTeacherData>, IAdditionalTeacherData>> result  = new List<IKurs<ITeacherToCourse<IAdditionalTeacherData>, IAdditionalTeacherData>>();
    if (takeXtr)
        using (var context = new Context())
        {
            var courses = context.XtrCourses.Include(x=>x.TeachersToCourses).Where(_someCourseFilterForAgs);
            result.Concat(await courses.ToListAsync()).Cast<IKurs<ITeacherToCourse<IAdditionalTeacherData>, IAdditionalTeacherData>>();
        }

    using (var context = new Context())
    {
        var courses = context.AgsCourses.Include(x=>x.TeachersToCourses).Where(_someCourseFilterForAgs);
        result.Concat(await courses.ToListAsync()).Cast<IKurs<ITeacherToCourse<IAdditionalTeacherData>, IAdditionalTeacherData>>();
    }
    return result;
}

As you can see, I tried casting them both with .Cast<IKurs<ITeacherToCourse<IAdditionalTeacherData>, IAdditionalTeacherData>>() (that throws an InvalidCastException)

These are my Course classes, both implementing IKurs<T1<T2>, T1> but their T1 and T2 are different (but still they use the same interfaces):

public class XtrCourse : Core_Xtr_Course, IKurs<XtrTeacherToCourse, XtrAdditionalTeacherData>
{
    public int Nr { get; set; }
    // properties

    public ICollection<XtrTeacherToCourse> TeachersToCourses { get; set; }
}

public class AgsCourse : Core_Ags_Course, IKurs<AgsTeacherToCourse, AgsAdditionalTeacherData>
{
    public int Nr { get; set; }
    // properties

    public ICollection<AgsTeacherToCourse> TeachersToCourses { get; set; }
}

public interface IKurs<TTeacherToCourse, TAdditionalTeacherData>
        where TTeacherToCourse : ITeacherToCourse<TAdditionalTeacherData>
        where TAdditionalTeacherData: IAdditionalTeacherData
{
    int Nr { get; set; }

    ICollection<TTeacherToCourse> TeachersToCourses { get; set; }
}

public interface ITeacherToCourse<T> where T : IAdditionalTeacherData
{
    int Nr { get; set; }
    T AdditionalTeacherData { get; set; }
}

public interface IAdditionalTeacherData
{
    // properties
}

classes AgsTeacherToCourse and XtrTeacherToCourse both implement ITeacherToCourse classes AgsTeacherToCourse and XtrTeacherToCourse both implement ITeacherToCourse

How can I merge them to one list?

In real, both course-lists come from different contexts. That's why I'm initiating the context in GetCourses() twice.

解决方案

One of the main problems is

interface ITeacherToCourse<T> where T : IAdditionalTeacherData
{
    int Nr { get; set; }
    T AdditionalTeacherData { get; set; }
}

class XtrTeacherToCourse : ITeacherToCourse<XtrAdditionalTeacherData>
{
    public int Nr { get; set; }
    public XtrAdditionalTeacherData AdditionalTeacherData { get; set; }
}

class AgsTeacherToCourse : ITeacherToCourse<AgsAdditionalTeacherData>
{
    public int Nr { get; set; }
    public AgsAdditionalTeacherData AdditionalTeacherData { get; set; }
}

The interface contract defines that you can only set a value to AdditionalTeacherData of type XtrAdditionalTeacherData for XtrAdditionalTeacherData and AgsAdditionalTeacherData for AgsTeacherToCourse.

How can we ensure this contract when we were able to

ITeacherToCourse<IAdditionalTeacherData> ttc = new XtrTeacherToCourse();
ttc.AdditionalTeacherData = new AgsAdditionalTeacherData();

If you do not want to set the AdditionalTeacherData property then you can declare the interface like

interface ITeacherToCourse<out T> where T : IAdditionalTeacherData
{
    int Nr { get; set; }
    T AdditionalTeacherData { get; }
}

AdditionalTeacherData is now readonly and T is an out T.

Now we are able to

ITeacherToCourse<IAdditionalTeacherData> ttc; 
ttc = new XtrTeacherToCourse();
ttc = new AgsTeacherToCourse();

With the collections it is the same.

The total interface declaration

interface IAdditionalTeacherData
{

}

interface ITeacherToCourse<out T> where T : IAdditionalTeacherData
{
    int Nr { get; set; }
    T AdditionalTeacherData { get; }
}

interface IKurs<out TTeacherToCourse, out TAdditionalTeacherData>
    where TTeacherToCourse : ITeacherToCourse<TAdditionalTeacherData>
    where TAdditionalTeacherData : IAdditionalTeacherData
{
    int Nr { get; set; }
    IEnumerable<TTeacherToCourse> TeachersToCourses { get; }
}

and the implementing classes

class XtrAdditionalTeacherData : IAdditionalTeacherData
{

}

class XtrTeacherToCourse : ITeacherToCourse<XtrAdditionalTeacherData>
{
    public int Nr { get; set; }
    public XtrAdditionalTeacherData AdditionalTeacherData { get; set; }
}

class XtrCourse : IKurs<XtrTeacherToCourse, XtrAdditionalTeacherData>
{
    public int Nr { get; set; }
    public ICollection<XtrTeacherToCourse> TeachersToCourses { get; set; }
    // explicit implementation
    IEnumerable<XtrTeacherToCourse> IKurs<XtrTeacherToCourse, XtrAdditionalTeacherData>.TeachersToCourses => TeachersToCourses;
}

class AgsAdditionalTeacherData : IAdditionalTeacherData
{

}

class AgsTeacherToCourse : ITeacherToCourse<AgsAdditionalTeacherData>
{
    public int Nr { get; set; }
    public AgsAdditionalTeacherData AdditionalTeacherData { get; set; }
}

class AgsCourse : IKurs<AgsTeacherToCourse, AgsAdditionalTeacherData>
{
    public int Nr { get; set; }
    public ICollection<AgsTeacherToCourse> TeachersToCourses { get; set; }
    // explicit implementation
    IEnumerable<AgsTeacherToCourse> IKurs<AgsTeacherToCourse, AgsAdditionalTeacherData>.TeachersToCourses => TeachersToCourses;
}

and now we can add the instances without any cast

var collection = new List<IKurs<ITeacherToCourse<IAdditionalTeacherData>, IAdditionalTeacherData>>();

collection.Add(new XtrCourse());
collection.Add(new AgsCourse());

这篇关于投放并合并两个相同接口的列表,但不同类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆