将List <concrete>转换为List <inheritedinterface>而不使用.ToList()复制操作

时间:2016-02-23 22:55:02

标签: c# list servicestack ienumerable covariance

我在List和IEnumerable之间的协方差/逆变方面遇到了一些麻烦,很可能我并不完全理解这个概念。我的类必须是具有Concrete属性的Concrete,以便它们可以使用ServiceStack进行序列化(SS可以正确地反向反序列化接口,它们最终为null属性,我之前发现了mythz的一个帖子,声明他们没有#&# 39;我想支持IoC并且你的DTO应该只是混凝土。如果这种态度发生了变化,或者有人知道快速的解决方法,那就太好了。)

关于我们的架构:

  • 我们有一个EF Code First,它将在Schema项目(DLL)
  • 中拥有像User这样的实体
  • 我们在Interfaces项目(DLL)中有IUserModel的接口
  • 我们有一个UserModel,它具有与User类似的属性,但在Models项目(DLL)中添加了更多以便于作为Domain和DTO模型的存储。
  • 我们在像CreateUser这样的服务项目中有一个实际的ServiceStack DTO,它继承了UserModel(以保持服务项目中的代码量减少,因为它实际上是与{的相同属性{1}},但使用ServiceStack路由,我们可以对UserModelUserModel等使用相同的CreateUser。)

下面是我们的Domain模型中我们基本上拥有的内容片段。有超过200个对象与数据库中的表有关,但实际的EF代码不是第一个模型,所以我们可以在它们之间保留一个抽象层。

UpdateUser

直到今天,我们认为这是有效的,因为在我们的Workflows层,我们正在尝试编程接口,它正在向// Interface is in a lower level project that only has // interfaces in it, no concretes public interface IHaveNotesBaseModel { List<INoteModel> Notes { get; set; } } // Concrete implements the interface explicitly so it can have // the Concrete for ServiceStack serialization/deserialization public class UserModel : IHaveNotesBaseModel { public List<NoteModel> Notes { get; set; } List<INoteModel> IHaveNotesBaseModel.Notes { get { return Notes?.ToList<INoteModel>(); } set { Notes = value?.Cast<NoteModel>().ToList(); } } } 列表中添加最终映射的内容,但我们今天发现了一个场景如果将User.Notes传递给某个函数,IUserModel已添加到NoteModel,但如果您稍后调用具体Notes,则它不会那个对象。

我们一直在研究如何解决这个问题,并发现Notes正在制作原件的副本,这似乎是它无法正常工作的原因。我们需要一种从具体到接口继承的方法,而不需要复制列表。

因此,我们所知道的因为ServiceStack而无法做到的事情是:

  1. 更改为.ToList<INoteModel>():ServiceStack无法反序列化IEnumerable,因为它是一个界面
  2. 执行投射IEnumerable<T>:投射例外
  3. (List<INoteModel>)Notes.Cast<T>:施放例外
  4. 之后进行投射

1 个答案:

答案 0 :(得分:0)

试试这个

 public class UserModel : IHaveNotesBaseModel
    {
        public List<NoteModel> Notes { get; set; }
        List<INoteModel> IHaveNotesBaseModel.Notes
        {
            get { return Notes.Cast<INoteModel>().ToList(); }
            set { Notes = value.Cast<NoteModel>().ToList(); }
        }
    }

完整示例:

 class Program
    {
        static void Main(string[] args)
        {

            UserModel um = new UserModel();

            um.Notes = new List<NoteModel>();
            um.Notes.Add(new NoteModel { MyProperty = 1 });
            um.Notes.Add(new NoteModel { MyProperty = 100 });
            um.Notes.Add(new NoteModel { MyProperty = 10 });
            um.Notes.Add(new NoteModel { MyProperty = 10000 });

            List<INoteModel> Notes = um.Notes.Cast<INoteModel>().ToList();
            ((IHaveNotesBaseModel)um).Notes = Notes;



        }


    }

    // Interface is in a lower level project that only has
    // interfaces in it, no concretes
    public interface IHaveNotesBaseModel
    {
        List<INoteModel> Notes { get; set; }
    }
    // Concrete implements the interface explicitly so it can have
    // the Concrete for ServiceStack serialization/deserialization
    public class UserModel : IHaveNotesBaseModel
    {
        public List<NoteModel> Notes { get; set; }
        List<INoteModel> IHaveNotesBaseModel.Notes
        {
            get { return Notes.Cast<INoteModel>().ToList(); }
            set { Notes = value.Cast<NoteModel>().ToList(); }
        }
    }