请注意,这与该帖子有关,但是我有一个扩展的问题。相关问题回答了特定的通用部分。
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,所以我想保存所有特殊类型的属性(视频/帖子)。因此,我想避免在基类和专门类之间进行大量的来回回想。
我可能设计出了完全错误或过于复杂的设计。欢迎所有输入。
答案 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();