Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
bnuzhouwei opened this issue May 24, 2022 · 4 comments

Comments

@bnuzhouwei
Copy link

bnuzhouwei commented May 24, 2022

.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.
@slozier
Copy link
Contributor

slozier commented May 24, 2022

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.

@bnuzhouwei
Copy link
Author

bnuzhouwei commented May 25, 2022

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()

@bnuzhouwei
Copy link
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)

@slozier
Copy link
Contributor

slozier commented May 25, 2022

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
Projects
None yet
Development

No branches or pull requests

2 participants