0

I have an Encounter type and a Response that inherits it:

[BsonKnownTypes(typeof(Request), typeof(Response))]
public abstract class Encounter {
    public ObjectId Id { get; set; }
}
// .. some more Encounter subtypes ...
public class Response : Encounter {
    public bool IsResponded;
}

I want to be able to pass an Encounter or a subtype of it to the Db.UpdateEncounterAsync() method:

class Db {
    private IMongoCollection<Encounter> EncounersCollection;
    // ... stuff ...
    public Db() {
        EncounersCollection = InitCollection();
    }
    // ... stuff ...
    public async Task UpdateEncounterAsync<TEncounter, TField>(
        TEncounter encounter, Expression<Func<TEncounter, TField>> fieldFuncExpr)
        where TEncounter : Encounter
    {
        var value = fieldFuncExpr.Compile()(encounter);
        var updateDefinition = Builders<Encounter>.Update
            .Set(fieldFuncExpr, value); // Error CS1503

        var updateResult = await EncounersCollection.UpdateOneAsync(
            e => e.Id == encounter.Id, updateDefinition);
    }
}

In the following way:

Response response = GetResponse();
response.IsResponded = true;
// update just the IsResponded field of the response object:
UpdateEncounterAsync(response, r => r.IsResponded);

But my UpdateEncounterAsync doesn't compile:

Error CS1503 Argument 1: cannot convert from 'System.Linq.Expressions.Expression<System.Func<TEncounter, TField>>' to 'MongoDB.Driver.FieldDefinition<DataModel.Encounter, TField>'

That's because fieldFuncExpr is of type Expression<Func<TEncounter, TField>>, where TEncounter : Encounter, but Builders<Encounter>.Update.Set(expr, value) expects expr of type Expression<Func<Encounter, TField>> and not the generic TEncounter.

Is there an elegant way around it?

svick
  • 236,525
  • 50
  • 385
  • 514
Tar
  • 8,529
  • 9
  • 56
  • 127
  • that's likely the delegate `Contravariance` at work - did you try specifying the generic parameter in `Set` like `Set` as that seems to be generic as well (and your field is TEcounter etc.). It may also be due to you using the `Builders` so that's where you should start I think. It's hard to tell for sure, w/o `a small working example`, it's much easier to reason with a code in front. And I have no clue about MongoDb. In short you can't cast Func to Func, e.g. see [this](http://stackoverflow.com/a/10102063/417747) – NSGaga-mostly-inactive Jun 11 '16 at 23:33
  • @NSGaga, I can't change `Set`, it's an external library code. But the link you gave explains it perfectly, thanks. – Tar Jun 13 '16 at 10:30
  • np - and what I meant is you could use different generic parameter, no need for an external code - I think `Builders` is what I meant or `Set`, i.e. the way you're calling it – NSGaga-mostly-inactive Jun 13 '16 at 18:19

0 Answers0