Microsoft Developer Network > Página principal de foros > Phoenix > How to add and reference a new field within Generic Class
Formular una preguntaFormular una pregunta
 

PreguntaHow to add and reference a new field within Generic Class

  • jueves, 25 de junio de 2009 21:35AAyoub Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     Tiene código

    Hi,

    I’m working with Phoenix for .Net Assembly Transformation and my question is how we can add a new field to a generic Class and then load it.

    Suppose for instance we have the following Generic Class :

    public class Test<T>
    {
        private T value;       
    
        public Test(T value)
        {
            this.value = value;            
        }
        public T Value
        {
            get { return value; }
            set { this.value = value; }
        }        
    }
    

    And we need to transform this to

    public class Test<T>
    {
        private T value; 
        int newfield;
    
        public Test(T value)
        {
            this.value = value;            
        }
        public T Value
        {
            get { return value; }
            set { this.value = value; }
        }        
    
        public void MyMethod(int t)
        {
            newfield = t;
        }
    }
    

    When I consider the field as a usual field, I’m able to generate the modified generic class. However the PEVerify tool complain with the following Error :

    System.BadImageFormatException: Fields inside generic classes must be referenced using MemberRefs, even in the same module as the class.

    After some try I noted that to reference a field within the generic class we have to load the field of the class instantiated with the type variable “!0” as follows :

     

    Phx.Collections.TypeList typeList = Phx.Collections.TypeList.New(Phx.GlobalData.GlobalLifetime);            
                typeList.Append(testType.TypeVariableTypeList.Head.Data);  
    Phx.Types.AggregateType insta = testType.Instantiate(typeList);
    
    

     

    However this works only for an existing field because when we add a new field to the generic class, this field does not appear in the instantiated class. Even, if I try to add the field manually I get exception error.

    Can somebody give me a guidance please?

    Thank you!

     


Todas las respuestas

  • viernes, 26 de junio de 2009 16:46AAyoub Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     Tiene código

    Hi,

    Here a workaround for the previous question. To load a field, I use the following Function:

     

    public Phx.IR.ValueInstruction ldfld(Phx.Symbols.FieldSymbol fieldsymbol, bool append)
    {
    
        Phx.IR.ValueInstruction inst = Phx.IR.ValueInstruction.NewUnary(funit, Phx.Targets.Architectures.Msil.Opcode.ldfld,
            stackslot,
            Phx.IR.MemoryOperand.New(funit,
                fieldsymbol.Field, null,
                stackslot,
                0, Phx.Alignment.NaturalAlignment(fieldsymbol.Type),
                funit.AliasInfo.AllHeapMemoryTag,
                funit.SafetyInfo.SafeTag));
    
        funit.Legalize.Instruction(inst);
    
        if (fieldsymbol.EnclosingAggregateType.IsGeneric)
        {
            Phx.Collections.TypeList typeList = Phx.Collections.TypeList.New(Phx.GlobalData.GlobalLifetime);
            foreach (Phx.Types.TypeVariableType typeVar in fieldsymbol.EnclosingAggregateType.TypeVariableTypeList)
            {
                typeList.Append(typeVar);
            }
            Phx.Types.AggregateType instance = fieldsymbol.EnclosingAggregateType.Instantiate(typeList);
            Phx.Symbols.FieldSymbol thisfield = instance.FieldSymbolList;
            while (thisfield != null)
            {
                if (thisfield.UninstantiatedFieldSymbol == fieldsymbol)
                {
                    thisfield.IsToolGenerated = false;
                    thisfield.NeedsFixup = true;
                    thisfield.MustBeEmittedInMetadata = true;
                    inst.SourceOperand.ResetField(thisfield.Field);
                    break;
                }
                thisfield = thisfield.NextFieldSymbol;
            }        
        }
        if (append) appendInst.InsertBefore(inst);
        return inst;
    }
    

     

    When the field is newly added, we have to create the memory operand before; elsewhere the field is not populated in the FieldSymbolList of the instantiated class.

    A better and more general solution for this problem will be appreciated.

  • sábado, 04 de julio de 2009 2:29AAyoub Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     Tiene código

    Hi,

    The following code shows how we can obtain a generic class function symbol newly created to do a call from another function of the same generic class. We have to create a function symbol with a visibility ClrTokenReference and append it to the instantiated class.

    public Phx.Symbols.FunctionSymbol ResetFunction(Phx.Symbols.FunctionSymbol funcsymbol)
    {
        
        if (funcsymbol.EnclosingAggregateType.IsGeneric)
        {
            Phx.Collections.TypeList typeList = Phx.Collections.TypeList.New(Phx.GlobalData.GlobalLifetime);
            foreach (Phx.Types.TypeVariableType typeVar in funcsymbol.EnclosingAggregateType.TypeVariableTypeList)
            {
                typeList.Append(typeVar);
            }
    
            Phx.Types.AggregateType instance = funcsymbol.EnclosingAggregateType.Instantiate(typeList);
            Phx.Symbols.FunctionSymbol thisfunction = Phx.Symbols.FunctionSymbol.New(moduleUnit.SymbolTable, 0, funcsymbol.Name, funcsymbol.FunctionType, Phx.Symbols.Visibility.ClrTokenReference);
    
            instance.AppendMethodSymbol(thisfunction);
            instance.TypeSymbol.InsertInLexicalScope(thisfunction, thisfunction.Name);                                        
            thisfunction.MustBeEmittedInMetadata = true;                                                          
            thisfunction.UninstantiatedFunctionSymbol = funcsymbol;
            return thisfunction;
        }
        else
            return funcsymbol;
    }
    
    • Marcado como respuestaAAyoub sábado, 04 de julio de 2009 2:33
    • EditadoAAyoub sábado, 04 de julio de 2009 2:33
    • Desmarcado como respuestaAAyoub sábado, 04 de julio de 2009 2:34
    •