Reputation: 3
I have a class that has multiple generic fields and a generic method that has to use an field according to it's type parameter. Is this possible and how to do this ?
public class MongoService
{
private readonly IMongoCollection<User> users;
private readonly IMongoCollection<Function> functions;
private readonly IMongoCollection<Group> groups;
public MongoService(IMongoSettings settings)
{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.Database);
users = database.GetCollection<User>("user");
functions = database.GetCollection<Function>("function");
groups = database.GetCollection<Group>("group");
}
// User, Function and Group derives from MongoDocument
public async Task<T> GetById<T>(string id, string[] fieldToFetch) where T : MongoDocument
{
FilterDefinition<T> filter = Builders<T>.Filter.Eq("id", id);
ProjectionDefinition<T> projection = Builders<T>.Projection.Exclude("_id");
// SOMETHING should be :
// - users if GetById<User> is called
// - functions if GetById<Function> is called
// - groups if GetById<Group> is called
var document = await SOMETHING // ?
.Find(filter)
.Project<T>(projection)
.FirstOrDefaultAsync();
return document;
}
}
Upvotes: 0
Views: 485
Reputation: 858
Easy. You can just use: if (typeof(T) == typeof(Function))
. But if the fields all work the same you should prefer Zohar's solution
Upvotes: 0
Reputation: 82474
I would just add a private method to get the relevant collection, instead of keeping them as members of the class:
private IMongoCollection<T> GetCollection<T>()
{
var collectionName = typeof(T).Name.ToLowerInvariant();
return database.GetCollection<T>(collectionName);
}
and then use it like this:
public async Task<T> GetById<T>(string id, string[] fieldToFetch) where T : MongoDocument
{
// ... filter and projection code here ...
return await GetCollection<T>()
.Find(filter)
.Project<T>(projection)
.FirstOrDefaultAsync();
}
Note: This only works well if you name the collection the same as the type you use to represent it in c#, only with all lower letters - as the code in the question shows.
Upvotes: 2