c# - 如何创建可以将通用存储库作为输入的设计服务模式?
问题描述
请注意,这与这篇文章有关,但我有一个扩展的问题。相关问题回答了特定的通用部分。
首先我有我的模型:
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,所以我想保存专用类型(视频/帖子)的所有属性。所以我想避免在基类和专业类之间进行大量的来回转换。
我可能设计的完全错误或过于复杂。欢迎所有输入。
解决方案
在您之前的问题中,您可以使用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();
推荐阅读
- bash - 在新位置使用现有目录结构创建符号链接
- r - 在r中移动数据框中多列的值
- java - 带有 PATCH 方法的 Java 11 HttpRequest
- c# - 有没有办法从变量向泛型类添加类型约束?
- python - 关于Python超多继承的问题
- android-studio - Unity Android Build 在拆分 apk 和拆分二进制文件后未运行
- java - 我错过了尝试将 PlSql 语法与 Antlr4 一起使用的步骤吗?
- ios - 字体在 xcode 的属性检查器中不可见
- powershell - 为什么 Get-Item $PSScriptRoot 在由 Jenkins master 运行时会引发异常?
- python - 动态表目标调用“未找到”错误