动态转换为通用类型

时间:2014-02-07 10:40:36

标签: c# generics dynamic casting

我正在尝试访问System.Activities.Statements.Switch对象的Cases.Values属性。问题是我无法在运行时将Activity对象转换为Switch<>类型(从中派生出来)。

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);
        }
    }
}

此外,

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

抛出一个错误,该属性不存在,而调试器显示它不是真的。 T对我来说无关紧要 - 我只需要Cases集合。

修改

实际上,我找到的解决方案比我设定的解决方案更清晰。

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

2 个答案:

答案 0 :(得分:2)

你不能。

但不是你的循环,而是:

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

并在同一个类中定义一个新方法:

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

答案 1 :(得分:1)

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);
        }
}