Search code examples
fody

Issue accessing fields in generic base class using Fody


Consider the following test code structure:

class TestClass<T>
{
    public object TestObject;
}

class TestClass2<T> :TestClass<T>
{
    public int TestMethod()
    {}
}

When I add Instruction.Create(OpCodes.Ldfld, TestObjectField) to TestMethod, I get the following result:

ldfld class Object TestNamespace.TestClass`1::TestObject

This causes an issue in the secure plugin system of Dynamics CRM (more information could be found here). However, when I add TestObject = new object() to TestMethod, I get the following result, which runs fine:

ldfld class Object class TestNamespace.TestClass`1<!T>::TestObject

This only happens when the object I am trying to access is in a generic base class. Is there a way that I can simulate the desired result from within Fody please?

UPDATE:

I managed to partially solve the issue by using the following lines:

var testObjectFieldRef = testObjectFieldDefinition?.Resolve().GetGeneric();
var testClassTypeRef = testObjectFieldRef?.DeclaringType.Resolve().GetGeneric();

if (testClassTypeRef != null)
{
    testObjectFieldRef.DeclaringType = testClassTypeRef;
}

It seems that by default the ModuleDefinition does not provide a generic type/field definition; so it has to be done explicitly. In addition, the types of the generic parameters are not specified, so it's still an issue.


Solution

  • I managed to solve this issue by using the following code (reference):

    var genericBaseType = (GenericInstanceType) testClassTypeRef.BaseType;
    var genericArgs = genericBaseType .GenericArguments;
    var fullBaseTypedName = genericBaseType.ElementType.MakeGenericInstanceType(genericArgs.ToArray()).FullName
    

    Which returns ldfld class Object class TestNamespace.TestClass`1<!T>::TestObject as required. It will also fill in the type of the type parameter (in place of <!T>) if given in the derived class.