5,699,997 members and growing! (19,344 online)
Email Password   helpLost your password?
Languages » C# » General     Intermediate

Dynamic Properties implementation using C# generics

By SteveLi-Cellbi

Dynamic properties implementation using C# generics
C# 2.0, C#, Windows, .NET, .NET 2.0VS2005, Visual Studio, Dev

Posted: 30 Oct 2007
Updated: 30 Oct 2007
Views: 7,330
Bookmarked: 22 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
14 votes for this Article.
Popularity: 4.01 Rating: 3.50 out of 5
2 votes, 14.3%
1
2 votes, 14.3%
2
1 vote, 7.1%
3
1 vote, 7.1%
4
8 votes, 57.1%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

Some programming tasks require dynamic nature of properties exposed by an object. E.g. it might be needed to access object property by a given key, it might be needed to get all object properties and iterate over them. Dynamic properties are useful when you need to manage them at runtime, when your object is already instantiated. In this article we are going to create simple implementation of dynamic properties using C# programming language. We'll use generics for our dynamic properties to make the implementation more flexible and to avoid boxing operations when value types are used for underlying property values.

Using the code

DynamicProperty Abstract Class

First of all let's define what we need from a dynamic property. Generally speaking dynamic property should allow us to get or set value associated with it if any. Dynamic property may also be complex and may contain child dynamic properties, thus forming complex property tree, so we will also need methods to add or remove child dynamic properties and method to check if child property exists. For most tasks it's ok to reference dynamic property by its string name, so we will use string parameter to reference child dynamic properties.

Here is the list of basic functionality we'll need:

  • Get or set value of dynamic property.
  • Get or set value of child property using string name.
  • Add or remove child property.
  • Check if child property exists.

This is a general set of operations we will create inside our dynamic property abstract class. In this article we will not cover methods to access a collection of all child dynamic properties, however it doesn't look to hard to implement this, so we'll leave this implementation as an exercise.

Here is the C# code for the DynamicProperty abstract class:

/// <summary />

/// Abstract class for all dynamic properties.

/// </summary />

public abstract class DynamicProperty<T>
{
  // public methods...

  /// <summary />

  /// Gets value of child property with the given name.

  /// </summary />

  /// <typeparam name="TValue" />The value type of dynamic property.</typeparam />

  /// The name of the property to get.

  public abstract TValue GetValue<TValue>(string name);

  /// <summary />

  /// Sets value of child property with the given name.

  /// </summary />

  /// <typeparam name="TValue" />The value type of dynamic property.</typeparam />

  /// The name of the property to get.

  /// The value to set.

  public abstract void SetValue<TValue>(string name, TValue value);

  /// <summary />

  /// Returns true if there is a child property

  /// with the given name inside this dynamic property.

  /// </summary />

  /// The name of the property to check.

  public abstract bool HasProperty(string name);

  /// <summary />

  /// Adds child property to this dynamic property.

  /// </summary />

  /// <typeparam name="TValue" />The value type of dynamic property.</typeparam />

  /// The property to add.

  public abstract void AddProperty<TValue>(string name,
DynamicProperty<TValue> property);

  /// <summary />

  /// Removes child property from this dynamic property.

  /// </summary />

  /// The name of the property to remove.

  public abstract void RemoveProperty(string name);

  /// <summary />

  /// Gets child dynamic property with the given name.

  /// </summary />

  /// <typeparam name="TValue" />The value type of dynamic property.</typeparam />

  /// The name of the child property to get.

  public abstract DynamicProperty<TValue> GetProperty<TValue>(string name);

  // public properties...

  /// <summary />

  /// Gets or sets value of this property.

  /// </summary />

  public abstract T Value
  {
    get;
    set;
  }
}

Note that we are using generic abstract class with T generic type parameter for the property value type. This type parameter is only used as a return type of Value abstract property, and there is no field with T type inside DynamicProperty class, so T type parameter will be needed for descendants. DynamicProperty class defines several abstract methods for adding or removing child dynamic properties. GetValue and SetValue methods can be used to access value of a child property with the specified name. All methods for child property manipulation have TValue generic type parameter (except for HasProperty method, since it just needs only child property name).

SimplePropery Class

DynamicProperty class is not useful by itself as it contains only abstract methods, we can do nothing yet. So we need to define simple DynamicProperty descendant to represent leaf dynamic property: SimpleProperty. SimpleProperty doesn't have any child properties and doesn't allow adding or removing them, instead it only has a value.

Here is the C# code for the SimpleProperty class:

/// <summary />

/// Simple dynamic property.

/// </summary />

public class SimpleProperty<T> : DynamicProperty<T>
{
  T _value;

  // constructors...

  public SimpleProperty(T value)
  {
    _value = value;
  }

  // public methods...

  public override TValue GetValue<TValue>(string name)
  {
    throw new 
InvalidOperationException("Can't get property value.");
  }
  public override void SetValue<TValue>(string name, TValue value)
  {
    throw new
InvalidOperationException("Can't set property value.");
  }
  public override bool HasProperty(string name)
  {
    return false;
  }
  public override void AddProperty<TValue>(string name,
DynamicProperty<TValue> property)
  {
    throw new
InvalidOperationException("Can't add child properties.");
  }
  public override void RemoveProperty(string name)
  {
    throw new
InvalidOperationException("Can't remove child properties.");
  }
  public override DynamicProperty<TValue> GetProperty<TValue>
(string name)
  {
    throw new
InvalidOperationException("Can't get child properties.");
  }

  // public properties...

  public override T Value
  {
    get { return _value; }
    set { _value = value; }
  }
}

Now we have an ability to create simple dynamic property and assign a value to it. Let's try to create simple properties with string, boolean and integer value types, here is the sample code:

// String property:

DynamicProperty<string> stringProperty = 
new SimpleProperty<string>("StringValue");
stringProperty.Value = "Hello";
Console.WriteLine("String property value: {0}", stringProperty.Value);

// Boolean property:

DynamicProperty<bool> boolProperty = new SimpleProperty<bool>(false);
boolProperty.Value = true;
Console.WriteLine("Boolean property value: {0}", 
boolProperty.Value);

// Integer property:

DynamicProperty<int> intProperty = new SimpleProperty<int>(20);
intProperty.Value = 100;
Console.WriteLine("Integer property value: {0}", intProperty.Value);

The sample above is pretty clear: each property has its own type and value passed inside simple property constructor. Value is used to get or set associated property value. Simple property is basic implementation of dynamic property and it is not very useful alone. Again we are going to create another descendant of the DynamicProperty abstract class to support child dynamic properties.

ComplexProperty Class

The most interesting part of this article starts here as complex dynamic property class contains core implementation of our dynamic properties concept. I should mention that the same concept we used to represent dynamic properties of text element and formatting objects inside our product for text document text manipulation. Complex property class overrides abstract methods of its ancestor class and adds implementation to support child dynamic properties. We will use System.Collections.Generic.Dictionary class to store child properties.

Here is the C# code for the ComplexProperty class:

/// <summary>

/// Complex dynamic property implementation.

/// </summary>

public class ComplexProperty<T> : DynamicProperty<T>
{
  Dictionary<string, object> _properties;

  // constructors...

  public ComplexProperty()
  {
  }

  // private properties...

  Dictionary<string, object> Properties
  {
    get
    {
      if (_properties == null)
        _properties = new Dictionary<string, object>();
      return _properties;
    }
  }

  // public methods...

  public override TValue GetValue<TValue>(string name)
  {
    DynamicProperty<TValue> property = GetProperty<TValue>(name);
    if (property != null)
      return property.Value;
    return default(TValue);
  }
  public override void SetValue<TValue>(string name, TValue value)
  {
    DynamicProperty<TValue> property = GetProperty<TValue>(name);
    if (property != null)
      property.Value = value;
  }
  public override bool HasProperty(string name)
  {
    return _properties == null ? false : Properties.ContainsKey(name);
  }
  public override void AddProperty<TValue>(string name,
DynamicProperty<TValue> property)
  {
    if (HasProperty(name))
      throw new
InvalidOperationException("Can't add property.");

    Properties.Add(name, property);
  }
  public override void RemoveProperty(string name)
  {
    Properties.Remove(name);
  }
  public override DynamicProperty<TValue> GetProperty<TValue>
(string name)
  {
    if (!HasProperty(name))
      throw new
InvalidOperationException("Can't get property.");

    DynamicProperty<TValue> property = Properties[name] as 
DynamicProperty<TValue>;
    if (property == null)
      throw new
InvalidOperationException("Invalid type specified.");

    return property;
  }

  // public properties...

  public override T Value
  {
    get { return default(T); }
    set { }
  }
}

Note that ComplexProperty doesn't have any value associated with it, so when creating complex property we will use object type as generic type argument (it is also possible to declare ComplexPoperty class without generic type parameters, we'll leave this as an exercise). Inside GetValue and SetValue methods we call GetProperty method first and then get or set underlying property value. We can use complex properties together with simple properties to build complex dynamic property trees. Let's try to create complex dynamic property with three simple child properties from the example above:

// Create complex dynamic property and add child properties:

DynamicProperty<object> complexProperty = new ComplexProperty<object>();
complexProperty.AddProperty("StringProperty", stringProperty);
complexProperty.AddProperty("BooleanProperty", boolProperty);
complexProperty.AddProperty("IntegerProperty", intProperty);

// We can get or set value of child properties now:

complexProperty.SetValue<string>("StringProperty", 
"Child String Value");
Console.WriteLine("Complex property child string: {0}", 
complexProperty.GetValue<string>("StringProperty"));

complexProperty.SetValue<bool>("BooleanProperty", false);
Console.WriteLine("Complex property child booean: {0}", 
complexProperty.GetValue<bool>("BooleanProperty"));

complexProperty.SetValue<int>("IntegerProperty", 200);
Console.WriteLine("Complex property child integer: {0}", 
complexProperty.GetValue<int>("IntegerProperty"));

In the example above we create an instance of ComplexProperty class and then add child dynamic properties. Then we can use SetValue and GetValue methods to easily access child property values. Note that AddProperty method calls do not have type arguments specified, this is possible because C# compiler uses type inference to determine which type to use for TValue generic type parameter.

Exposing Dynamic Properties

Simple and complex dynamic properties can be used to dynamically create property trees using AddProperty and RemoveProperty methods. However, we found that it is good idea to expose dynamic properties as fixed via class properties when it is known that properties won't change at runtime. E.g. for customer class we can say for sure that FirstName and LastName properties won't be ever removed from customer data type, so it makes sense to expose these dynamic properties. Here is the C# code example:

/// <summary>

/// Customer properties.

/// </summary>

public class CustomerDetails : ComplexProperty<object>
{
  // constructors...

  public CustomerDetails()
  {
    AddProperty("FirstName", 
new SimpleProperty<string>(String.Empty));
    AddProperty("LastName", 
new SimpleProperty<string>(String.Empty));
  }

  // public properties...

  public string FirstName
  {
    get { return GetValue<string>("FirstName"); }
    set { SetValue<string>("FirstName", value); }
  }
  public string LastName
  {
    get { return GetValue<string>("LastName"); }
    set { SetValue<string>("LastName", value); }
  }
}

In the example above we expose FirstName and LastName string properties, but we call GetValue and SetValue methods inside getter and setter of these properties. This makes it easy to work with CustomerDetails class without even knowing that FirtName and LastName properties are dynamic properties.

Conclusion

In this article we've implemented a simple dynamic properties concept using C# generic classes. Dynamic property is very flexible concept and can be used when you need to have a class with dynamic nature.

Points of Interest

There is still functionality left behind the scope of this article, e.g. Typed Relationship, Dynamic Property Knowledge Level and Extrinsic concepts. For related reading we would recommend "Dealing with Properties" article by Martin Fowler.

History

  • October 31th, 2007 : Initial Release

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

SteveLi-Cellbi


I'm excited about computers and programming, since my school days. I have master's degree in software development and at the moment I'm a software developer at Cellbi Software.
Occupation: Web Developer
Location: United States United States

Other popular C# articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 6 of 6 (Total in Forum: 6) (Refresh)FirstPrevNext
GeneralConfusedmemberWedant2:07 22 Nov '07  
GeneralRe: ConfusedmemberSteveLi-Cellbi10:40 22 Nov '07  
GeneralSo simple, yest so nice!memberRoefes21:18 7 Nov '07  
GeneralReally nice, Steve!memberJoe Ginger0:14 7 Nov '07  
GeneralthanksmemberFxTeddy0:09 2 Nov '07  
GeneralRe: thanksmemberSteveLi-Cellbi7:13 2 Nov '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 30 Oct 2007
Editor:
Copyright 2007 by SteveLi-Cellbi
Everything else Copyright © CodeProject, 1999-2008
Web20 | Advertise on the Code Project