Tarec
Tarec

Reputation: 3255

Dynamic casting to a generic type

I'm trying to get to the Cases.Values property of System.Activities.Statements.Switch object. The problem is that I cannot cast Activity object at runtime to Switch<> type (which derives from it).

var switchType = activity.GetType();
bool isSwitch = (switchType.IsGenericType && switchType.GetGenericTypeDefinition() == typeof(Switch<>));

if (isSwitch)
{
    Type[] genericArgumentTypes = switchType.GetGenericArguments();
    if (genericArgumentTypes.Length > 0)
    {
        var switchStatement = (Switch<genericArgumentTypes[0]>) activity;  //that's incorrect
        foreach (var aCase in switchStatement.Cases.Values)
        {
            ProcessActivity(aCase, dataSets, context);
        }
    }
}

Also,

dynamic switchStatement = activity;
foreach (var aCase in switchStatement.Cases.Values)
{
    ProcessActivity(aCase, dataSets, context);
}

throws an error, that the property is not there, while debugger is showing it's not true. The T is irrelevant for me - I need only the Cases collection.

EDIT

Actually, I've found even cleaner solution, than the one I set as an answer.

dynamic switchStatement = activity;
var cases = switchStatement.Cases as IEnumerable;
if (cases != null)
{
    foreach (dynamic aCase in cases)
    {
        ProcessActivity(aCase.Value);
    }
}

Upvotes: 1

Views: 1124

Answers (2)

Olivier
Olivier

Reputation: 5688

You can't.

But instead of your loop, put:

var process = typeof(CurrentHelperClass).GetMethod("ProcessSwitch`1").MakeGenericMethod(typeof(genericArgumentTypes[0]));
 process.Invoke(null,new object[]{activity});

and define a new method in the same class:

static void ProcessSwitch<T>(Switch<T> switchStatement)
{
    foreach (var aCase in switchStatement.Cases.Values)
    {
        ProcessActivity(aCase, dataSets, context);
    }
}

Upvotes: 2

Tamir Vered
Tamir Vered

Reputation: 10287

var switchType = activity.GetType();
var prop = switchType.GetProperty("Cases", System.Reflection.BindingFlags.Public 
            | System.Reflection.BindingFlags.Instance); //move it outside of the method and use the same property for every time you call the method since it's performance expansive.
bool isSwitch = (switchType.IsGenericType && switchType.GetGenericTypeDefinition() == typeof(Switch<>));

if (isSwitch)
{
        IEnumerable dictionary = prop.GetValue(activity,null) as IDictionary;
        foreach (var item in dictionary.Values)
        {
            ProcessActivity(item, dataSets, context);
        }
}

Upvotes: 1

Related Questions