Lucas Pouchot
Lucas Pouchot

Reputation: 3

C# : Use different fields from class in a generic method according to it's type parameter

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

Answers (2)

Patrick Beynio
Patrick Beynio

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

Zohar Peled
Zohar Peled

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

Related Questions