2014-02-07 5 views
1

Я пытаюсь добраться до объекта Cases.Values объекта System.Activities.Statements.Switch. Проблема в том, что я не могу использовать объект 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.

EDIT

На самом деле, я нашел даже чистое решение, чем я установить в качестве ответа.

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

Как переменная 'activity' определяется? – Dennis

+0

http://msdn.microsoft.com/en-us/library/vstudio/system.activities.activity(v=vs.100).aspx 'Switch <>' наследуется от класса 'Activity'. – Tarec

ответ

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

Спасибо. Тем не менее, я получаю 'Операции с ограниченной привязкой не могут выполняться для типов или методов, для которых ContainsGenericParameters является истинным. Исключение для назначения словарного объекта. – Tarec

+0

Отредактировано, теперь это сработает. вам просто нужно выполнить метод 'GetValue()' для свойства, которое вы получили с помощью 'GetType()' dynamicamically –

+0

К сожалению, GetValue возвращает значение null, если оно выбрано в 'IDictionary'. Если я не буду использовать его и использовать в качестве динамического, и я получу объект словаря, но снова - я не смогу получить свойство «Значения». – Tarec

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

Коммутатор <> является частью пространства имен System.Activities. Как я могу заставить библиотечный класс реализовать интерфейс? – Tarec

+0

О, хорошо, я этого не понимал. Вы сами инициируете этот класс? Если да, вы можете определить класс MySwitch : Switch , ISwitch. Если нет, я предложу новый ответ (немного сложнее) – Olivier

+0

№ 'Switch <>' - это узел в рабочем процессе. Я просматриваю каждый узел (Activity), и я не могу изменить используемые типы действий. – Tarec

Смежные вопросы