C
Chuck Hartman
I am trying to create a dynamic assembly that contains a dynamic type with
the seveal dynamically created members like the static ones shown
immediately below.
A private field like:
private string customerName;
A public property with a Description Attribute like:
[Description("This is the long description of this property.")]
public string CustomerName
{
get { return customerName; }
set { customerName = value; }
}
I have taken bits and pieces from several of the builder class examples from
MSDN and constructed the example below. It seems to work correctly except
for the Description Attribute does not seem to be present. I did not see a
direct way to set that with the Property Builder methods, so I tried the
System.Reflection.Emit.PropertyBuilder.SetCustomAttribute(). I think I must
not be understanding some part part of the picture. I would appreciate any
help. Thanks.
--
Chuck Hartman
The complete modified sample console app code follows:
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
using System.ComponentModel;
class PropertyBuilderDemo
{
public static Type BuildDynamicTypeWithProperties()
{
AppDomain myDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName,
AssemblyBuilderAccess.Run);
ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule("MyModule");
TypeBuilder myTypeBuilder = myModBuilder.DefineType("CustomerData",
TypeAttributes.Public);
FieldBuilder customerNameBldr = myTypeBuilder.DefineField("customerName",
typeof(string),
FieldAttributes.Private);
PropertyBuilder custNamePropBldr =
myTypeBuilder.DefineProperty("CustomerName",
PropertyAttributes.HasDefault,
typeof(string),
new Type[] { typeof(string) });
//*** begin added code
Type[] ctorParams = new Type[] { typeof(string) };
ConstructorInfo classCtorInfo =
typeof(DescriptionAttribute).GetConstructor(ctorParams);
CustomAttributeBuilder myCABuilder = new CustomAttributeBuilder(
classCtorInfo,
new object[] { "This is the long description of this property." });
custNamePropBldr.SetCustomAttribute(myCABuilder);
//*** end added code
// First, we'll define the behavior of the "get" property for CustomerName
as a method.
MethodBuilder custNameGetPropMthdBldr =
myTypeBuilder.DefineMethod("GetCustomerName",
MethodAttributes.Public,
typeof(string),
new Type[] { });
ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();
custNameGetIL.Emit(OpCodes.Ldarg_0);
custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);
custNameGetIL.Emit(OpCodes.Ret);
// Now, we'll define the behavior of the "set" property for CustomerName.
MethodBuilder custNameSetPropMthdBldr =
myTypeBuilder.DefineMethod("SetCustomerName",
MethodAttributes.Public,
null,
new Type[] { typeof(string) });
ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();
custNameSetIL.Emit(OpCodes.Ldarg_0);
custNameSetIL.Emit(OpCodes.Ldarg_1);
custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);
custNameSetIL.Emit(OpCodes.Ret);
// Last, we must map the two methods created above to our PropertyBuilder
to
// their corresponding behaviors, "get" and "set" respectively.
custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);
return myTypeBuilder.CreateType();
}
public static void Main()
{
Type custDataType = BuildDynamicTypeWithProperties();
PropertyInfo[] custDataPropInfo = custDataType.GetProperties();
foreach (PropertyInfo pInfo in custDataPropInfo)
{
Console.WriteLine("Property '{0}' created!", pInfo.ToString());
PropertyDescriptor propDesc =
TypeDescriptor.GetProperties(custDataType)[pInfo.Name];
Console.WriteLine(" Description: '{0}' created!", propDesc.Description);
}
Console.WriteLine("---");
// Note that when invoking a property, you need to use the proper
BindingFlags -
// BindingFlags.SetProperty when you invoke the "set" behavior, and
// BindingFlags.GetProperty when you invoke the "get" behavior. Also note
that
// we invoke them based on the name we gave the property, as expected, and
not
// the name of the methods we bound to the specific property behaviors.
object custData = Activator.CreateInstance(custDataType);
custDataType.InvokeMember("CustomerName", BindingFlags.SetProperty,
null, custData, new object[]{ "Joe User" });
Console.WriteLine("The customerName field of instance custData has been
set to '{0}'.",
custDataType.InvokeMember("CustomerName", BindingFlags.GetProperty,
null, custData, new object[]{ }));
Console.WriteLine("Done");
}
}
the seveal dynamically created members like the static ones shown
immediately below.
A private field like:
private string customerName;
A public property with a Description Attribute like:
[Description("This is the long description of this property.")]
public string CustomerName
{
get { return customerName; }
set { customerName = value; }
}
I have taken bits and pieces from several of the builder class examples from
MSDN and constructed the example below. It seems to work correctly except
for the Description Attribute does not seem to be present. I did not see a
direct way to set that with the Property Builder methods, so I tried the
System.Reflection.Emit.PropertyBuilder.SetCustomAttribute(). I think I must
not be understanding some part part of the picture. I would appreciate any
help. Thanks.
--
Chuck Hartman
The complete modified sample console app code follows:
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
using System.ComponentModel;
class PropertyBuilderDemo
{
public static Type BuildDynamicTypeWithProperties()
{
AppDomain myDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName,
AssemblyBuilderAccess.Run);
ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule("MyModule");
TypeBuilder myTypeBuilder = myModBuilder.DefineType("CustomerData",
TypeAttributes.Public);
FieldBuilder customerNameBldr = myTypeBuilder.DefineField("customerName",
typeof(string),
FieldAttributes.Private);
PropertyBuilder custNamePropBldr =
myTypeBuilder.DefineProperty("CustomerName",
PropertyAttributes.HasDefault,
typeof(string),
new Type[] { typeof(string) });
//*** begin added code
Type[] ctorParams = new Type[] { typeof(string) };
ConstructorInfo classCtorInfo =
typeof(DescriptionAttribute).GetConstructor(ctorParams);
CustomAttributeBuilder myCABuilder = new CustomAttributeBuilder(
classCtorInfo,
new object[] { "This is the long description of this property." });
custNamePropBldr.SetCustomAttribute(myCABuilder);
//*** end added code
// First, we'll define the behavior of the "get" property for CustomerName
as a method.
MethodBuilder custNameGetPropMthdBldr =
myTypeBuilder.DefineMethod("GetCustomerName",
MethodAttributes.Public,
typeof(string),
new Type[] { });
ILGenerator custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();
custNameGetIL.Emit(OpCodes.Ldarg_0);
custNameGetIL.Emit(OpCodes.Ldfld, customerNameBldr);
custNameGetIL.Emit(OpCodes.Ret);
// Now, we'll define the behavior of the "set" property for CustomerName.
MethodBuilder custNameSetPropMthdBldr =
myTypeBuilder.DefineMethod("SetCustomerName",
MethodAttributes.Public,
null,
new Type[] { typeof(string) });
ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();
custNameSetIL.Emit(OpCodes.Ldarg_0);
custNameSetIL.Emit(OpCodes.Ldarg_1);
custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);
custNameSetIL.Emit(OpCodes.Ret);
// Last, we must map the two methods created above to our PropertyBuilder
to
// their corresponding behaviors, "get" and "set" respectively.
custNamePropBldr.SetGetMethod(custNameGetPropMthdBldr);
custNamePropBldr.SetSetMethod(custNameSetPropMthdBldr);
return myTypeBuilder.CreateType();
}
public static void Main()
{
Type custDataType = BuildDynamicTypeWithProperties();
PropertyInfo[] custDataPropInfo = custDataType.GetProperties();
foreach (PropertyInfo pInfo in custDataPropInfo)
{
Console.WriteLine("Property '{0}' created!", pInfo.ToString());
PropertyDescriptor propDesc =
TypeDescriptor.GetProperties(custDataType)[pInfo.Name];
Console.WriteLine(" Description: '{0}' created!", propDesc.Description);
}
Console.WriteLine("---");
// Note that when invoking a property, you need to use the proper
BindingFlags -
// BindingFlags.SetProperty when you invoke the "set" behavior, and
// BindingFlags.GetProperty when you invoke the "get" behavior. Also note
that
// we invoke them based on the name we gave the property, as expected, and
not
// the name of the methods we bound to the specific property behaviors.
object custData = Activator.CreateInstance(custDataType);
custDataType.InvokeMember("CustomerName", BindingFlags.SetProperty,
null, custData, new object[]{ "Joe User" });
Console.WriteLine("The customerName field of instance custData has been
set to '{0}'.",
custDataType.InvokeMember("CustomerName", BindingFlags.GetProperty,
null, custData, new object[]{ }));
Console.WriteLine("Done");
}
}