Create code at runtime with Reflection in .NET C#: Properties

In the previous post of this short series we saw how to add a field to our custom type using Reflection. In this finishing post we’ll look at properties and how to save our dynamic assembly.

Properties can be created in two ways. First we can use the PropertyBuilder class:

PropertyBuilder priceProperty = simpleType.DefineProperty("Price", PropertyAttributes.None, typeof(int), Type.EmptyTypes);

This will create a standard property called Price which returns an integer and has no input parameters. You’d write it like this in Visual Studio:

public int Price { get; set; }

For some reason the PropertyAttributes enumeration doesn’t let you refine the characteristics of the property as much as e.g. MethodAttributes or FieldAttributes do. In case you’d like to define the visibility of the property you need to turn to the MethodBuilder object and use it in a special way. The methods will perform the get/set methods separately. The following code example creates a get and set method:

MethodAttributes pricePropertyAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
MethodBuilder getPriceBuilder = simpleType.DefineMethod("get_Price", pricePropertyAttributes, typeof(int), Type.EmptyTypes);
MethodBuilder setPriceBuilder = simpleType.DefineMethod("set_Price", pricePropertyAttributes, null, new Type[] { typeof(int) });
priceProperty.SetGetMethod(getPriceBuilder);
priceProperty.SetSetMethod(setPriceBuilder);

The SpecialName and HideBySig values indicate that these methods are special and will not be part of the public interface. The name of the get/set methods must follow a convention: “get_XXX” and “set_XXX” where ‘XXX’ is the name of the property like get_Price.

The special methods can be associated with the property using the SetGetMethod and SetSetMethod methods of the PropertyBuilder object.

Once you’re done with your custom assembly then it can be persisted on disk using the Save method of AssemblyBuilder:

assemblyBuilder.Save(assemblyFileName);

View all posts on Reflection here.

Advertisement

Dynamically invoking a property with Reflection in .NET C#

Say you do not have access to a .NET assembly at compile time but you want to run code in it. It’s possible to dynamically load an assembly and run code in it without early access.

Here we’ll see how to invoke a property of a type in a referenced assembly.

In this post we saw how to invoke a constructor and here how to invoke a method of a Type.

Open Visual Studio 2012/2013 and create a new C# class library project called Domain. Add the following Customer class to it:

public class Customer
{
	private string _name;

	public Customer() : this("N/A")
	{}

	public Customer(string name)
	{
		_name = name;
	}

        public int AccountValue { get; set; }
}

Build the solution and locate the compiled Domain.dll library. It should be located in either the Debug or Release folder within the bin folder depending on the compilation configuration in VS. Copy the .dll and put it somewhere else on your main drive where you can easily find it. We’re pretending that you got the library from another source but you for whatever reason cannot reference it at compile time. E.g. the source is loaded into your app as a plugin which follows some naming conventions so that your code can unwrap it and invoke its code.

Let’s see how we can get hold of the AccountValue property. First we’ll invoke the overloaded constructor:

string pathToDomain = @"C:\Studies\Reflection\Domain.dll";
Assembly domainAssembly = Assembly.LoadFrom(pathToDomain);
Type customerType = domainAssembly.GetType("Domain.Customer");
Type[] stringArgumentTypes = new Type[] { typeof(string) };
ConstructorInfo stringConstructor = customerType.GetConstructor(stringArgumentTypes);
object newStringCustomer = stringConstructor.Invoke(new object[] { "Elvis" });

Then we locate the AccountValue method and set its value. We also provide an object to represent the integer argument to the property. Keep in mind that properties are “normal” methods as we saw in this post so we need to supply an argument to the Set method:

PropertyInfo accountProperty = customerType.GetProperty("AccountValue");
accountProperty.SetValue(newStringCustomer, 1200);

Next we read the property value using the Get version:

int accountPropertyValue = Convert.ToInt32(accountProperty.GetValue(newStringCustomer));

‘accountPropertyValue’ will be 1200 as expected.

View all posts on Reflection here.

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: