private object InvokeInternal(IOperationResult result) { var type = Type.GetType(TargetType, true); var flags = MemberFlags.Public | MemberFlags.NonPublic | (IsStatic ? MemberFlags.Static : MemberFlags.Instance); var method = type.GetMethodsEx(flags).First(FilterMethod); var viewModels = CollectViewModels(result); var items = new Dictionary <Type, object>(); if (result.Source != null) { items[result.Source.GetType()] = result.Source; } object[] args; if (FirstParameterSource) { var parameter = method.GetParameters()[0]; object firstParam; if (!items.TryGetValue(parameter.ParameterType, out firstParam)) { var viewModel = viewModels.FirstOrDefault(model => model.GetType() == parameter.ParameterType); firstParam = viewModel ?? result.Source; } args = new[] { firstParam, result }; } else { args = new object[] { result } }; if (IsStatic) { return(method.InvokeEx(null, args)); } object target = Target; if (target == null) { if (!items.TryGetValue(type, out target)) { target = ToolkitServiceProvider.GetOrCreateDefault(type); items[type] = target; } } if (Snapshots != null) { foreach (var fieldSnapshot in Snapshots) { fieldSnapshot.Restore(type, target, items, viewModels, null, result); } } return(method.InvokeEx(target, args)); }
public bool Restore(Type targetType, object target, Dictionary <Type, object> items, ICollection <IViewModel> viewModels, string awaiterResultType, IOperationResult result) { var field = targetType.GetFieldEx(Name, MemberFlags.NonPublic | MemberFlags.Public | MemberFlags.Instance); if (field == null) { TraceError(null, targetType); return(false); } switch (FieldType) { case BuilderField: var type = Type.GetType(TypeName, true); var createMethod = type.GetMethodEx("Create", MemberFlags.NonPublic | MemberFlags.Public | MemberFlags.Static); var startMethod = type.GetMethodEx("Start", MemberFlags.NonPublic | MemberFlags.Public | MemberFlags.Instance); if (createMethod == null || startMethod == null || !startMethod.IsGenericMethodDefinition) { ((IAsyncStateMachine)target).MoveNext(); return(true); } var builder = createMethod.Invoke(null, Empty.Array <object>()); SetValue(field, target, builder); startMethod.MakeGenericMethod(typeof(IAsyncStateMachine)) .Invoke(builder, new[] { target }); break; case AwaiterField: var awaiterType = typeof(SerializableAwaiter <>).MakeGenericType(Type.GetType(awaiterResultType, true)); var instance = Activator.CreateInstance(awaiterType, result); SetValue(field, target, instance); break; case AsyncOperationField: var opType = typeof(AsyncOperation <>).MakeGenericType(Type.GetType(awaiterResultType, true)); var opInstance = (IAsyncOperation)Activator.CreateInstance(opType); AsyncOperation <object> .TrySetResult(opInstance, result); SetValue(field, target, opInstance); break; case AnonymousClass: var anonType = Type.GetType(TypeName, true); object anonClass; if (!items.TryGetValue(anonType, out anonClass)) { anonClass = ToolkitServiceProvider.GetOrCreateDefault(anonType); foreach (var snapshot in Snapshots) { snapshot.Restore(anonType, anonClass, items, viewModels, awaiterResultType, result); } items[anonType] = anonClass; } SetValue(field, target, anonClass); break; case NonSerializableField: object service; if (State == null) { var serviceType = Type.GetType(TypeName, true); if (!items.TryGetValue(serviceType, out service)) { if (field.Name.Contains("CachedAnonymousMethodDelegate")) { service = field.GetValueEx <object>(target); } else if (!ToolkitServiceProvider.TryGet(serviceType, out service)) { service = field.GetValueEx <object>(target); TraceError(field, targetType); } items[serviceType] = service; } } else { var stateManager = ToolkitServiceProvider.OperationCallbackStateManager; service = stateManager == null ? State : stateManager.RestoreValue(State, field, items, viewModels, result, DataContext.Empty); } SetValue(field, target, service); break; case SerializableField: SetValue(field, target, IsType ? Type.GetType((string)State, false) : State); break; case ViewModelField: var viewModel = RestoreViewModel(viewModels, items, result); if (viewModel == null) { TraceError(field, targetType); return(false); } SetValue(field, target, viewModel); break; } return(true); }