Skip to content

MongoDb GetCollection error: get MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true. #816

Open

Description

@bnuzhouwei

.NET6 and IronPython 2.7.11

call the function:

def cnt():
    import System, clr
    clr.AddReference("MongoDB.Bson")
    clr.AddReference("MongoDB.Driver")
    from MongoDB.Bson import *
    from MongoDB.Driver import *
    connStr = "....."
    client = MongoClient(connStr)
    database = client.GetDatabase("db")    
    dataset = database.GetCollection[BsonDocument]("collection")
    return dataset.CountDocument(BsonDocument()) 
cnt()

database.GetCollection raise error:

System.InvalidOperationException: MongoDB.Driver.IMongoCollection`1[TDocument] GetCollection[TDocument](System.String, MongoDB.Driver.MongoCollectionSettings) is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.

Activity

  1. slozier commented on May 24, 2022

    @slozier
    Contributor

    The issue appears to be something like this:

    public abstract class MyBaseClass {
        public abstract T GetCollection<T>();
    
        // this is just a helper to get an instance of the internal class
        public static MyBaseClass test() {
            return new MyInternalClass();
        }
    }
    
    internal sealed class MyInternalClass : MyBaseClass {
        public override T GetCollection<T>() {
            throw new NotImplementedException();
        }
    }
    MyBaseClass.test().GetCollection[object]

    which results in:

    SystemError: T GetCollection[T]() is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.
    

    A possible workaround is to enable private bindings with the PrivateBinding option.

  2. bnuzhouwei commented on May 25, 2022

    @bnuzhouwei
    Author

    Thanks, you are right, the code in mongodb driver is:

    namespace MongoDB.Driver
    {
    	// Token: 0x020000C0 RID: 192
    	internal sealed class MongoDatabaseImpl : MongoDatabaseBase
    }
    

    Internal without public....,

    But how to to enable private bindings with the PrivateBinding option? Can add any paramters to the CreateEngine method?

    IronPython.Hosting.Python.CreateEngine()
  3. bnuzhouwei commented on May 25, 2022

    @bnuzhouwei
    Author

    I modified the source code, changed the class MongoDatabaseImpl from internal to public, and recompile it.

    namespace MongoDB.Driver
    {
    	public sealed class MongoDatabaseImpl : MongoDatabaseBase
    }

    The GetCollection in above code run correctly, but in mongodb, there are many methods with default value as default(CancellationToken), i.e.

    long CountDocuments(FilterDefinition<TDocument> filter, CountOptions options = null, CancellationToken cancellationToken = default(CancellationToken));

    but in IronPython, when we call the method:

    GetCollection[BsonDocument]("collection")

    got

    IronPython.Runtime.Exceptions.TypeErrorException: expected CancellationToken, got NoneType

    I seems that IronPython does't support default value for structs, such as default(CancellationToken)

  4. slozier commented on May 25, 2022

    @slozier
    Contributor

    But how to to enable private bindings with the PrivateBinding option? Can add any paramters to the CreateEngine method?

    You can enable private binding like this:

    Python.CreateEngine(new Dictionary<string, object> { {"PrivateBinding", true} });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions