首页 > 解决方案 > 如何创建可以将通用存储库作为输入的设计服务模式?

问题描述

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

如何实例化泛型类

首先我有我的模型:

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,所以我想保存专用类型(视频/帖子)的所有属性。所以我想避免在基类和专业类之间进行大量的来回转换。

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

标签: c#generics

解决方案


在您之前的问题中,您可以使用out. T但是由于语言特性的限制,您不能使用in 方法参数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();

推荐阅读