Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define type of a property at runtime in .NET?

Tags:

c#

.net

types

In Winform application I have a class with 2 properties and I want the user to be able to choose the type of those properties.

This is what I made so far:

Class with the properties:

static public class DataGridColumnData
{
    public static object SearchColumn { get; set; }
    public static object ResultColumn { get; set; }
}

And the user can choose the type of the properties using a Combobox with DropDownList Style which has values like

System.String
System.Double
System.Int32
System.Boolean
System.DateTime 

Is there a way to make those properties to be types the ones that user chooses?

like image 588
user850010 Avatar asked Sep 16 '25 20:09

user850010


2 Answers

You can make your class generic:

static public class DataGridColumnData<T>
{ 
    public static T SearchColumn { get; set; } 
    public static T ResultColumn { get; set; } 
} 

Then, in your code, you can create a class of the desired type:

object myDataGridColumnData;
if (userSelection == "String") {
    myDataGridColumnData = new DataGridColumnData<string>();
} else if (userSelection == "Double") {
    myDataGridColumnData = new DataGridColumnData<double>();
} ...

Note that, technically, DataGridColumnData<string> is a completely different type than DataGridColumnData<int>, so object is the only common supertype. Thus, to be able to access the values of myDataGridColumnData in code, you might need to use a dynamic variable or (prefered) use some common interface or base class that returns the values typed as objects.

like image 119
Heinzi Avatar answered Sep 18 '25 17:09

Heinzi


There are ways to make the properties strongly typed in runtime using generics, but I am not sure how useful it is. Here is a solution either way:

Create an interface that is not strongly typed to facilitate interaction with the object:

public interface IDataGridColumnData
{
    object SearchColumnAsObject { get; set; }
    object ResultColumnAsObject { get; set; }
}

Create generic class that allows for the creation of strongly typed versions at runtime (and in code as well, of course), and that implements the interface:

public class DataGridColumnData<TSearch, TResult> : IDataGridColumnData
{
    public TSearch SearchColumn { get; set; }
    public static TResult ResultColumn { get; set; }
    public object SearchColumnAsObject
    {
        get { return SearchColumn; }
        set { SearchColumn = (TSearch)value; }
    }
    public object ResultColumnAsObject
    {
        get { return ResultColumn; }
        set { ResultColumn = (TResult)value; }
    }
}

Create a factory method that will manufacture strongly typed versions of the class, returning it as the object-typed interface:

private static IDataGridColumnData GetDataGridColumnData(
    Type searchType, Type resultType)
{
    var typedColumnDataType = typeof(DataGridColumnData<,>)
            .MakeGenericType(new[] { searchType, resultType });
    return (IDataGridColumnData)Activator.CreateInstance(typedColumnDataType);
}

...and put it to use:

IDataGridColumnData instance = GetDataGridColumnData(
    Type.GetType("System.Int32"),
    Type.GetType("System.String"));

// use the properties
instance.SearchColumnAsObject = 42; // works well
instance.SearchColumnAsObject = "42"; // throws exception
like image 24
Fredrik Mörk Avatar answered Sep 18 '25 16:09

Fredrik Mörk