如何创建可以将通用存储库作为输入的设计服务模式?

时间:2019-12-12 19:40:46

标签: c# generics

请注意,这与该帖子有关,但是我有一个扩展的问题。相关问题回答了特定的通用部分。

How to instantiate generic classes

首先我有我的模特:

public class BasePost
{
    public int Id { get; set; }
}

public class Video : BasePost
{
    public int VideoPro { get; set; }
}


public class Post : BasePost
{
    public int PostProp { get; set; }
}

现在我想要一个只能采用BasePost类型的存储库:

public interface IRepo<out T> where T : BasePost
{
    void Add(BasePost post);

}

public class Repo<T> : IRepo<BasePost> where T : BasePost
{
    public void Add(BasePost post)
    {

    }
}

我需要能够将存储库注入服务。我有不同的服务,其中一些专门用于帖子,一些专门用于视频:

public interface IService<out T> where T : BasePost
{
    void Run(IRepo<BasePost> repo);
}

public class FacebookService : IService<Post>
{
    public void Run(IRepo<Post> repo)
    {

    }
}

这是我的第一个问题:

  

“ FacebookService”未实现接口成员   'IService.Run(IRepo)'

我的最终目标是拥有多项服务,可以将其添加到一个公共变量中,例如:

IService service = null;
IRepo repo = null;
if (txtInput.Text == "Facebook")
{
    service = new FacebookService<Post>();
    repo = new Repo<Post>();

}
else
{
    service = new YoutubeService<Video>();
    repo = new Repo<Video>();               
}

service.Run(repo);

摘要: 我有一个回写到cosmos DB的仓库。因此,它可以采用从BasePost派生的任何类型。我想要传递给其他服务的仓库。但是,每种服务都只能处理一种模型(视频或邮政)。

因为数据已写入cosmos db,所以我想保存所有特殊类型的属性(视频/帖子)。因此,我想避免在基类和专门类之间进行大量的来回回想。

我可能设计出了完全错误或过于复杂的设计。欢迎所有输入。

1 个答案:

答案 0 :(得分:0)

在上一个问题中,您可以使用out解决案例问题。但是由于T的语言功能限制,无法在方法参数中使用out。您可以调整设计以将T用于可分配的方法。使用协变时,也很重要的一点是使用接口。

例如您的界面如下所示:

public interface IPost
{
    int Id { get; }
}

public interface IRepo<out T> where T : IPost
{
    void Add(BasePost post);
}

public interface IService<T> where T : IPost
{
    IRepo<T> Repository { get; }
    void Run();
}

实现基类以通过构造函数处理存储库初始化,以将其强制为依赖项。

public class BasePost : IPost
{
    public int Id { get; set; }
}

public class Repo<T> : IRepo<BasePost> where T : BasePost
{
    public void Add(BasePost post)
    {

    }
}

public abstract class Service : IService<IPost>
{
    public IRepo<IPost> Repository { get; private set; }

    public Service(IRepo<IPost> repository)
    {
        this.Repository = repository;
    }

    public abstract void Run();
}

您使用基类来实现服务:

public class FacebookService : Service
{
    public FacebookService(IRepo<IPost> repository) : base(repository)
    {
    }

    public override void Run()
    {
        throw new NotImplementedException();
    }
}

现在,您可以初始化服务对象并将它们分配给您的IService接口。

    IService<IPost> service = null;
    IRepo<IPost> repo = null;
    if (input == "Facebook")
    {
        repo = new Repo<Post>();
        service = new FacebookService(repo);
    }
    else
    {
        repo = new Repo<Video>();
        service = new YoutubeService(repo);
    }
    service.Run();