Microsoft Developer Network > Página Inicial dos Fóruns > Phoenix > How to add and reference a new field within Generic Class
Fazer uma PerguntaFazer uma Pergunta
 

PerguntaHow to add and reference a new field within Generic Class

  • quinta-feira, 25 de junho de 2009 21:35AAyoub Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     Contém 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 as Respostas

  • sexta-feira, 26 de junho de 2009 16:46AAyoub Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     Contém 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, 4 de julho de 2009 2:29AAyoub Medalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuárioMedalhas de usuário
     Contém 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 RespostaAAyoub sábado, 4 de julho de 2009 2:33
    • EditadoAAyoub sábado, 4 de julho de 2009 2:33
    • Não Marcado como RespostaAAyoub sábado, 4 de julho de 2009 2:34
    •