Reputation: 5275
I have an interface:
public interface ICrawlService<T> where T : SocialPostBase
{
Task<int> Crawl(int accountId, Disguise disguise, ISocialAccountRepository socialAccountRepository, ISocialRepository<T> socialRepository, ISocialCrawlJobRepository jobRepository, IInstrumentationRepository instrumentationRepository);
}
My social repository is:
public interface ISocialRepository<T> where T : class
{
IEnumerable<SocialPostCollection<T>> List { get; }
Task Add(SocialPostCollection<T> entity, string type);
Task AddPosts(List<T> entity, string type);
void Delete(SocialPostCollection<T> entity);
void Update(SocialPostCollection<T> entity);
T Find(string profileName, MediaType type);
}
I am looking for a polymorphic design so I can instantiate different classes into a single type. Something like:
var socialRepo = new SocialRepository<Video>(configration.CosmosDBServiceEndpoint, configration.CosmosDBSecret, configration.CosmosDBDatabaseId);
var socialRepo2 = new SocialRepository<Post>(configration.CosmosDBServiceEndpoint, configration.CosmosDBSecret, configration.CosmosDBDatabaseId);
ICrawlService<SocialPostBase> crawlService;
crawlService = new CrawlYoutubeProfileService();
var id = await crawlService.Crawl(jobId, null, _socialAccountRepo, socialRepo, _socialCrawlJobRepo, instrumentationRepo);
crawlService = new CrawlAnotherProfileService();
var id2 = await crawlService.Crawl(jobId, null, _socialAccountRepo, socialRepo2, _socialCrawlJobRepo, instrumentationRepo);
However it will not accept the base class for the generic parameter, I get following error.
Cannot implicitly convert type 'SocialCrawlServices.CrawlYoutubeProfileService' to 'SocialCrawlServices.ICrawlService'. An explicit conversion exists (are you missing a cast?)
So how do you make a generic polymorphic design? Is that not possible?
Upvotes: 0
Views: 64
Reputation: 491
The error says "An explicit conversion exists (are you missing a cast?)". The answer is to explicitly cast the implementing class as the interface:
crawlService = (ICrawlService<SocialPostBase>)new CrawlYoutubeProfileService();
crawlService = (ICrawlService<SocialPostBase>)new CrawlAnotherProfileService();
This should work as long as CrawlYoutubeProfileService
and CrawlAnotherProfileService
have type arguments that implement SocialPostBase
, like this:
class YoutubePost : SocialPostBase
{
}
class CrawlYoutubeProfileService : ICrawlService<YoutubePost>
{
}
Upvotes: 0
Reputation: 1953
Is that not possible?
No, it's possible. You just need to add out
before your generic parameter in ICrawlService
.
public interface ICrawlService<out T> where T : SocialPostBase
See Covariance and Contravariance in Generics.
Upvotes: 1