9

A read about creating types at runtime and i found it amazing. My goal is to create this class:

[DelimitedRecord(",")]
public class Person
{
    [FieldOrder(0)]
    private string firstName;

    [FieldOrder(1)]
    private string lastName;

    public string FirstName
    {
        get { return firstName; }
        set { firstName = value; }
    }

    public string LastName
    {
        get { return lastName; }
        set { lastName = value; }
    }
}

I did this:

//create the builder
AssemblyName assembly = new AssemblyName("FileHelpersTests");
AppDomain appDomain = System.Threading.Thread.GetDomain();
AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name);

//create the class
TypeBuilder typeBuilder = moduleBuilder.DefineType("Person", TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.AnsiClass |
                                                    TypeAttributes.BeforeFieldInit, typeof(System.Object));

//create the Delimiter attribute

//create the firstName field
FieldBuilder firstNameField = typeBuilder.DefineField("firstName", typeof(System.String), FieldAttributes.Private);

//create the firstName attribute [FieldOrder(0)]

//create the FirstName property
PropertyBuilder firstNameProperty = typeBuilder.DefineProperty("FirstName", PropertyAttributes.HasDefault, typeof(System.String), null);

//create the FirstName Getter
MethodBuilder firstNamePropertyGetter = typeBuilder.DefineMethod("get_FirstName", MethodAttributes.Public | MethodAttributes.SpecialName |
                                                                  MethodAttributes.HideBySig, typeof(System.String), Type.EmptyTypes);
ILGenerator firstNamePropertyGetterIL = firstNamePropertyGetter.GetILGenerator();
firstNamePropertyGetterIL.Emit(OpCodes.Ldarg_0);
firstNamePropertyGetterIL.Emit(OpCodes.Ldfld, firstNameField);
firstNamePropertyGetterIL.Emit(OpCodes.Ret);

//create the FirstName Setter
MethodBuilder firstNamePropertySetter = typeBuilder.DefineMethod("set_FirstName", MethodAttributes.Public | MethodAttributes.SpecialName |
                                                    MethodAttributes.HideBySig, null, new Type[] { typeof(System.String) });
ILGenerator firstNamePropertySetterIL = firstNamePropertySetter.GetILGenerator();
firstNamePropertySetterIL.Emit(OpCodes.Ldarg_0);
firstNamePropertySetterIL.Emit(OpCodes.Ldarg_1);
firstNamePropertySetterIL.Emit(OpCodes.Stfld, firstNameField);
firstNamePropertySetterIL.Emit(OpCodes.Ret);

//assign getter and setter
firstNameProperty.SetGetMethod(firstNamePropertyGetter);
firstNameProperty.SetSetMethod(firstNamePropertySetter);


//create the lastName field
FieldBuilder lastNameField = typeBuilder.DefineField("lastName", typeof(System.String), FieldAttributes.Private);

//create the lastName attribute [FieldOrder(1)]

//create the LastName property
PropertyBuilder lastNameProperty = typeBuilder.DefineProperty("LastName", PropertyAttributes.HasDefault, typeof(System.String), null);

//create the LastName Getter
MethodBuilder lastNamePropertyGetter = typeBuilder.DefineMethod("get_LastName", MethodAttributes.Public | MethodAttributes.SpecialName |
                                                                  MethodAttributes.HideBySig, typeof(System.String), Type.EmptyTypes);
ILGenerator lastNamePropertyGetterIL = lastNamePropertyGetter.GetILGenerator();
lastNamePropertyGetterIL.Emit(OpCodes.Ldarg_0);
lastNamePropertyGetterIL.Emit(OpCodes.Ldfld, lastNameField);
lastNamePropertyGetterIL.Emit(OpCodes.Ret);

//create the FirstName Setter
MethodBuilder lastNamePropertySetter = typeBuilder.DefineMethod("set_FirstName", MethodAttributes.Public | MethodAttributes.SpecialName |
                                                    MethodAttributes.HideBySig, null, new Type[] { typeof(System.String) });
ILGenerator lastNamePropertySetterIL = lastNamePropertySetter.GetILGenerator();
lastNamePropertySetterIL.Emit(OpCodes.Ldarg_0);
lastNamePropertySetterIL.Emit(OpCodes.Ldarg_1);
lastNamePropertySetterIL.Emit(OpCodes.Stfld, lastNameField);
lastNamePropertySetterIL.Emit(OpCodes.Ret);

//assign getter and setter
lastNameProperty.SetGetMethod(lastNamePropertyGetter);
lastNameProperty.SetSetMethod(lastNamePropertySetter);

I got stuck while creating those attributes:

  • The one at class level
  • The one at field level

This is what ILDASM shows when i click

  1. The constructor

    .class public auto ansi beforefieldinit FileHelpersTests.Person
        extends [mscorlib]System.Object
    {
        .custom instance void [FileHelpers]FileHelpers.DelimitedRecordAttribute::.ctor(string) = ( 01 00 01 2C 00 00 )           // ...,..
    } // end of class FileHelpersTests.Person
    
  2. The firstName field

    .field private string firstName
    .custom instance void [FileHelpers]FileHelpers.FieldOrderAttribute::.ctor(int32) = ( 01 00 00 00 00 00 00 00 ) 
    
7
  • 1
    What does “LE” mean? Does it mean the class attribute works now? In any case, what have you tried and how did that fail? Commented Jan 23, 2013 at 13:38
  • Also, it's usually much easier to generate code by using C#-level libraries, like CodeDOM (if it can do what you need) or Roslyn. Commented Jan 23, 2013 at 13:40
  • What exactly do you need help with? Does your attribute not work? Is there an exception? Commented Jan 23, 2013 at 13:41
  • With LE i ment that is a later edit Commented Jan 23, 2013 at 13:41
  • It now works, i just hurried and post it, anyway, it remains here as a full example of how to achieve it. Commented Jan 23, 2013 at 13:43

1 Answer 1

4

I made it work:

//create the Delimiter attribute
Type[] attributeParams = new Type[] { typeof(string) };
ConstructorInfo classCtorInfo = typeof(DelimitedRecordAttribute).GetConstructor(attributeParams);
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(classCtorInfo, new object[] { ";" });
typeBuilder.SetCustomAttribute(attributeBuilder);

This would do the job for the field attributes:

//create the firstName attribute [FieldOrder(0)]
Type[] firstNameFieldOrderAttributeParams = new Type[] { typeof(int) };
ConstructorInfo firstNameFieldOrderAttrInfo = typeof(FieldOrderAttribute).GetConstructor(firstNameFieldOrderAttributeParams);
CustomAttributeBuilder firstNameFieldOrderAttributeBuilder = new CustomAttributeBuilder(firstNameFieldOrderAttrInfo, new object[] { 0 });
firstNameField.SetCustomAttribute(firstNameFieldOrderAttributeBuilder);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.