Пример #1
0
        private static Func <object> GetCommandExecutionProviderConstructor(CommandExecutionProviderKey key)
        {
            Func <object> constructor;

            if (!CompiledConstructors.TryGetValue(key, out constructor))
            {
                var executionProviderType = typeof(CommandExecutionProvider <>).MakeGenericType(key.TargetType);
                var executionProviderCtor =
                    executionProviderType.GetConstructor(new[] { typeof(Type), typeof(string), typeof(string) });

                var executionProviderCtorParamaters = new Expression[]
                {
                    Expression.Constant(key.TargetType),
                    Expression.Constant(key.CanExecuteMethodName, typeof(string)),
                    Expression.Constant(key.ExecutedMethodName, typeof(string))
                };

                Debug.Assert(executionProviderCtor != null, "executionProviderCtor != null");
                var executionProviderCtorExpression = Expression.New(
                    executionProviderCtor,
                    executionProviderCtorParamaters);
                constructor = Expression.Lambda <Func <object> >(executionProviderCtorExpression).Compile();
            }

            return(constructor);
        }
Пример #2
0
        private static ICommandExecutionProvider GetCommandExecutionProvider(
            object target,
            string canExecuteMethodName,
            string executedMethodName)
        {
            if (target == _disconnectedItemSentinelValue)
            {
                return(null);
            }

            var key = new CommandExecutionProviderKey(target.GetType(), canExecuteMethodName, executedMethodName);
            ICommandExecutionProvider executionProvider;

            if (!ExecutionProviders.TryGetValue(key, out executionProvider))
            {
                try
                {
                    executionProvider = (ICommandExecutionProvider)GetCommandExecutionProviderConstructor(key)();
                }
                catch (TargetInvocationException)
                {
                    // Thanks to Mark Bergan for finding this issue!
                    // Unfortunately we have some nastiness around a performance optimization in C# 4.0.
                    // Because we are listening to DataContext events we may end up being provided a DataContext
                    // value that is an internal place holder for the DataContext of disconnected containers WPF.
                    // There is no easy way to detect this object, hence the reflection. Basically we just want to
                    // ignore any disconnected DataContext items. The best documentation I have found is located in
                    // Answer 10 on the forum located here:
                    // http://www.go4answers.com/Example/disconnecteditem-causing-it-115624.aspx
                    if (_disconnectedItemSentinelValue == null)
                    {
                        if (IsDisconnected(target))
                        {
                            _disconnectedItemSentinelValue = target;
                        }

                        ////var targetType = target.GetType();
                        ////if (targetType.FullName == "MS.Internal.NamedObject")
                        ////{
                        ////    var nameField = targetType.GetField("_name", BindingFlags.Instance | BindingFlags.NonPublic);
                        ////    if (nameField != null)
                        ////        if ((string)nameField.GetValue(target) == "DisconnectedItem")
                        ////        {
                        ////            _DisconnectedItemSentinelValue = target;
                        ////        }
                        ////}
                    }

                    if (target != _disconnectedItemSentinelValue)
                    {
                        throw;
                    }
                }

                ExecutionProviders.TryAdd(key, executionProvider);
            }

            return(executionProvider);
        }
Пример #3
0
        private static ICommandExecutionProvider GetCommandExecutionProvider(object target, string canExecuteMethodName, string executedMethodName)
        {
            if (target == _DisconnectedItemSentinelValue)
            {
                return(null);
            }

            var key = new CommandExecutionProviderKey(target.GetType(), canExecuteMethodName, executedMethodName);
            ICommandExecutionProvider executionProvider = null;

            _Lock.EnterUpgradeableReadLock();
            try
            {
                if (!_ExecutionProviders.TryGetValue(key, out executionProvider))
                {
                    _Lock.EnterWriteLock();
                    try
                    {
                        if (!_ExecutionProviders.TryGetValue(key, out executionProvider))
                        {
                            var executionProviderType = typeof(CommandExecutionProvider <>).MakeGenericType(key.TargetType);
                            var executionProviderCtor = executionProviderType.GetConstructor(new Type[] { typeof(Type), typeof(string), typeof(string) });
                            try
                            {
                                executionProvider = (ICommandExecutionProvider)executionProviderCtor.Invoke(new object[] { key.TargetType, key.CanExecuteMethodName, key.ExecutedMethodName });
                            }
                            catch (TargetInvocationException)
                            {
                                //
                                // Thanks to Mark Bergan for finding this issue!
                                // Unfortunately we have some nastiness around a performance optimization in C# 4.0.
                                // Because we are listening to DataContext events we may end up being provided a DataContext
                                // value that is an internal place holder for the DataContext of disconnected containers WPF.
                                // There is no easy way to detect this object, hence the reflection. Basically we just want to
                                // ignore any disconnected DataContext items. The best documentation I have found is located in
                                // Answer 10 on the forum located here:
                                // http://www.go4answers.com/Example/disconnecteditem-causing-it-115624.aspx

                                if (_DisconnectedItemSentinelValue == null)
                                {
                                    var targetType = target.GetType();
                                    if (targetType.FullName == "MS.Internal.NamedObject")
                                    {
                                        var nameField = targetType.GetField("_name", BindingFlags.Instance | BindingFlags.NonPublic);
                                        if (nameField != null)
                                        {
                                            if ((string)nameField.GetValue(target) == "DisconnectedItem")
                                            {
                                                _DisconnectedItemSentinelValue = target;
                                            }
                                        }
                                    }
                                }
                                if (target != _DisconnectedItemSentinelValue)
                                {
                                    throw;
                                }
                            }

                            _ExecutionProviders.Add(key, executionProvider);
                        }
                    }
                    finally
                    {
                        _Lock.ExitWriteLock();
                    }
                }
            }
            finally
            {
                _Lock.ExitUpgradeableReadLock();
            }
            return(executionProvider);
        }