How to invoke static method on internal static class

106 Views Asked by At

I have following code:

AvroSerializerSettings settings = new AvroSerializerSettings
{
 Resolver = new AvroPublicMemberContractResolver()
};

var schemaWriter = AvroSerializer.Create<ProductOrderConfirmation>(settings).WriterSchema;

var schema = schemaWriter.ToString();

All works fine. The AvroSerializer class is internal static class. I am trying to do the same thing but using Activator.CreateInstance as I want to pass to the create method a type I have created at run time. So I have the following code

Type classType = assembly.GetType("Sample."+typeName);

AvroSerializerSettings settings = new AvroSerializerSettings
{
   Resolver = new AvroPublicMemberContractResolver()
};


var avroSerializerType = 
Type.GetType("Microsoft.Hadoop.Avro.AvroSerializer`1,Microsoft.Hadoop.Avro-Core");

var productSerializerType = avroSerializerType.MakeGenericType(classType);

var writerSchema = productSerializerType.GetMethod("Create", BindingFlags.NonPublic | BindingFlags.Static)
.Invoke(null, new object[] { settings })
.GetType()
.GetProperty("WriterSchema")
.GetValue(null, null);

The GetMethod returns null. I have tried to call GetMethod without binding flags I have also tried GetMethods call to see if I have method Create but do not see it in the methods array.

2

There are 2 best solutions below

0
JuanR On

Use the non-generic string to get the type of your serializer:

var avroSerializerType = 
Type.GetType("Microsoft.Hadoop.Avro.AvroSerializer,Microsoft.Hadoop.Avro-Core");

Alternatively, you can use the type directly instead of using strings, if the assembly is referenced:

var avroSerializerType =typeof(Microsoft.Hadoop.Avro.AvroSerializer);

You can then get the method's info using the AvroSerializerSettings type in order to select the right signature:

var createMethod = avroSerializerType.GetMethod("Create", new[] {typeof(AvroSerializerSettings) });

Once you have the info, you can construct a generic version:

var constructedMethod = createMethod.MakeGenericMethod(typeof(AvroSerializerSettings));

You can then use the constructed generic method info to invoke in the way you describe:

var writerSchema = constructedMethod.Invoke(null, new object[] { settings })
.GetType()
.GetProperty("WriterSchema")
.GetValue(null, null);
0
Ismail On

With some modifications from Juans suggestion I have it working:

 AvroSerializerSettings settings = new AvroSerializerSettings
{
    Resolver = new AvroPublicMemberContractResolver()
};

var method = typeof(AvroSerializer).GetMethod("Create", new Type[] { typeof(AvroSerializerSettings) })
    .MakeGenericMethod(new[] { classType });

var createdTyped = method.Invoke(null, new object[] { settings });

var writerSchema = createdTyped.GetType().GetProperty("WriterSchema");

var actualValue = writerSchema.GetValue(createdTyped);

var writerSchemaTyped = (TypeSchema)actualValue;