Posts Tagged Generics

C#: Multiple Dynamic Properties on a Class Either Defined or with Generics

Using the class indexer of C# (abc[ xxx ] = yyy) we can create a class which has multiple dynamic properties associated by a string or whatever we want as the key for access. In the example below we use a string as our access key and holds a string as a value. The storage is accomplished by using a dictionary. See the Usage method below on how to access it.

public class MultipleDynamicProperties
{

    private Dictionary<string, string> _dynamicProperties = new Dictionary<string, string>();    
    
    // Index the data here  
    public string this[string key]
    {
        get
        {
            if ( _dynamicProperties.ContainsKey( key ) == false )
                _dynamicProperties.Add( key, string.Empty );

            return _dynamicProperties[key];
        }
        set
        {
            if ( _dynamicProperties.ContainsKey( key ) == false )
                _dynamicProperties.Add( key, value );
            else
            {
                _dynamicProperties[key] = value;
            }
        }
    }

    /// <summary>
    /// Example don't use in your code.
    /// </summary>
    public static void Usage()
    {
        MultipleDynamicProperties mdc = new MultipleDynamicProperties();

        mdc["Jabber"] = "1st Attempt";
        mdc["Jabber"] = "Wocky";
        mdc["Omega"] = "Man";

        Console.WriteLine("Jabber: " + mdc["Jabber"]); // Printers Jabber: wocky

    }

}

Using other index types say integer or enum, we can accomplish the same goal by changing or adding to our index’able properties of the class. We could have multiple accessors as long as the key is not the same. Below is an example using an enum as the key and a List<string> as the value returned:

public class MultipleDynamicPropertiesWithEnum
{
    public enum Operation
    {
        TargetA,
        TargetB,
    }

    private Dictionary<Operation, List<string>> _dynamicProperties = new Dictionary<Operation, List<string>>();


         // Index the data here  
    public List<string> this[Operation key]
    {
        get
        {
            if ( _dynamicProperties.ContainsKey( key ) == false )
                _dynamicProperties.Add( key, new List<string>() );

            return _dynamicProperties[key];
        }
        set
        {
            if ( _dynamicProperties.ContainsKey( key ) == false )
                _dynamicProperties.Add( key, value );
            else
            {
                _dynamicProperties[key] = value;
            }
        }
    }

    public static void Usage()
    {
        MultipleDynamicPropertiesWithEnum show = new MultipleDynamicPropertiesWithEnum();

        show[Operation.TargetA] = new List<string>() { "Jabber" };
        show[Operation.TargetB] = new List<string>() { "Wocky" };

        // Prints Jabberwocky 
        Console.WriteLine( show[Operation.TargetA][0] + show[Operation.TargetB][0] );
    }
}

 

Generic Option

But why limit ourselves, why not make the accessor generic, so the user/consumer can dictate what the keys and what data is returned. Here is the generic version where we mimic the hard coded version of string and string.

/// <summary>
/// This class has a generic indexor defined by the generic parameters specified
/// by the consumer.
/// </summary>
/// <typeparam name="KY">Key type to use to acces the value type to store.</typeparam>
/// <typeparam name="T">The value type to store.</typeparam>
/// <remarks>See Usage on how to use.</remarks>
public class MultipleDynamicPropertiesAsGeneric<KY, T>
{

    private Dictionary<KY, T> _dynamicProperties = new Dictionary<KY, T>();

    // Index the data here  
    public T this[KY key]
    {
        get
        {
            if ( _dynamicProperties.ContainsKey( key ) == false )
            {
                _dynamicProperties.Add( key, Activator.CreateInstance<T>() );
            }

            return _dynamicProperties[key];
        }
        set
        {
            if ( _dynamicProperties.ContainsKey( key ) == false )
                _dynamicProperties.Add( key, value );
            else
            {
                _dynamicProperties[key] = value;
            }
        }
    }

    public static void Usage()
    {
        MultipleDynamicPropertiesAsGeneric<string, string> show = new MultipleDynamicPropertiesAsGeneric<string, string>();

        show["Jabber"] = "Wocky";

        // Prints wocky 
        Console.WriteLine( show["Jabber"] );

    }

}
Share

Tags: ,

C#: Using Reflection to Instantiate a Generic Class in .Net

Reflection has many purposes, but what happens if one wants to instantiate a generic class? How does one specify the what makes the class generic to  instantiate it? The trick is to use the MakeGenericType to make the argument(s) and then call create Instance. Here is a code snippet:

Type d1 = typeof(List<>);

Type[] typeArgs = { typeof(string) };

Type makeme = d1.MakeGenericType(typeArgs);

object o = Activator.CreateInstance(makeme);

List<string> itsMe = o as List<string>;

Console.WriteLine((itsMe == null) ? "Failed" : "Succeeded");

Here is what is going on

  • Line 1 We get the type as normal.
  • Line 3 Create an array of the arguments we are interested in.
  • Line 5 Call MakeGenericType to do the magic
  • Line 7 Create the object.
Share

Tags: , ,