比较它继承的类(通过Foo是IBar)返回false:为什么?

时间:2016-05-27 09:18:26

标签: c# wpf xaml types comparison

我想要完成的事情

我希望能够将事件处理程序从一个类绑定到该控件的XAML中另一个类中对象按钮的Click事件:

例如:

<Button Click="{OtherClass.EventHandler}"/>

我的方法

我正在使用来自here

的近十年前的代码

我正在使用一个继承System.Windows.Input.ICommand接口的类,它基本上包含Action以减少我的生命......愚蠢:

public class Command : ICommand {
    private Action _ToExecute;
    public Action ToExecute{
        get{ return this._ToExecute; }
        set{ this._ToExecute = value; }
    }

    public Command( Action ToExecute ){ this._ToExecute = ToExecute; }

    public event EventHandler CanExecuteChanged; //Never Used
    public bool CanExecute( object parameter ){ return true; }
    public void Execute( object parameter ){
        this._ToExecute?.Invoke( );
    }
}

我在下面的类中使用了这个类,它扩展了Buttons的行为,以便能够将按钮的Click事件处理程序绑定到这些命令:

public static class ButtonClickBehavior{
    public static ReadOnly DependencyProperty[] Properties = 
        EventBehviourFactory.CreateCommandExecutionEventBehaviour(
            ButtonBase.ClickEvent, new string[]{ "Command", "Parameter" },
            typeof( ButtonClickBehavior ) );

    public static void SetCommand( DependencyObject o, ICommand value ){
        o.SetValue( Properties[ 0 ], value );
    }

    public static ICommand GetCommand( DependencyObject o ){
        return o.GetValue( Properties[ 0 ] as ICommand;
    }

    public static void SetParameter( DependencyObject o, object value ){
        o.SetValue( Properties[ 1 ], value );
    }

    public static object GetParameter( DependencyObject o ){
        return o.GetValue( Properties[ 1 ] );
    }
}

这个类使用上面提到的静态类:(严重依赖于上面引用的代码翻录代码)

public static class EventBehaviorFactory {
    public static DependencyProperty[] CreateCommandExecutionEventBehaviour(
        RoutedEvent routedEvent, string[] propertyNames, Type ownerType ){
        ExecuteCommandOnRoutedEventBehaviour
            CommandExecutor = new ExecuteCommandOunRoutedBehavior( routedEvent );

        DependencyProperty p = DependencyProperty.RegisterAttached(
            propertyNames[ 0 ], typeof( ICommand ), ownerType,
            new PropertyMetadata( null, CommandExecutor.PropertyChanged ) );

        if ( propertyNames.Count( ) > 1 )
            return new DependencyProperty[ ]{
                p, DependencyProperty.RegisterAttached(
                       propertyNames[ 1 ], typeof( ICommand ), ownerType,
                       new PropertyMetadata( null, CommandExecutor.PropertyChanged ) )
            };
        else return new DependencyProperty[ ] { p };
    }

    private class ExecuteCommandOnRoutedEventBehaviour : ExecuteCommandBehaviour {
        private readonly RoutedEvent _routedEvent;
        public ExecuteCommandOnRoutedEventBehaviour( RoutedEvent routedEvent ){
            this._routedEvent = routedEvent;
        }
        protected override void AdjustEventHandlers(
            DependencyObject sender, object oldValue, object newValue ){
            UIElement element = sender as UIElement;
            if ( oldValue != null )
                element.RemoveHandler(
                    _routedEvent, new RoutedEventHandler( EventHandler );
            if ( newValue != null )
                element.AddHandler(
                    _routedEvent, new RoutedEventHandler( EventHandler );

        }

        protected void EventHandler( object sender, RoutedEventArgs e ){
            HandleEvent( sender, e );
        }
    }

    internal abstract class ExecuteCommandBehaviour{
        protected DependencyProperty
            _commandProperty, _paramProperty;
        protected abstract void AdjustEventHandler(
            DependencyObject sender, object oldValue, object newValue );

        protected void HandleEvent( object sender, EventArgs e ){
            DependencyObject dp = sender as DependencyObject;
            if ( dp == null )
                return;

            ICommand cmd = dp.GetValue( _commandProperty ) as ICommand;
            if ( command == null )
                return;

            object param
            if ( this._paramProperty == null || ( 
                 param = dp.GetValue( this._paramProperty ) ) == null ){
                if ( cmd.CanExecute( e ) )
                    cmd.Execute( e );
            } else {
                if ( cmd.CanExecute( param ) )
                    cmd.Execute( param );
            }
        }

        public void PropertyChanged(
            DependencyObject sender, DependencyPropertyChangedEventArgs e ) {
            /*THIS IS THE LINE GIVING ME TROUBLE.*/
            if ( e.Property.PropertyType is ICommand ){
                //DO STUFF
            } else if ( /*Something ELSE*/ )
                //DO SOMETHING ELSE
        }
    }
}

我意识到我使用的代码来自一个已有近十年历史的源代码,并且应该存在一些应该能够做我想要的东西,但是对于我所有的谷歌搜索我都是空的(除了那个我继续打这个结果,所以我想了什么,我会修改它以满足我的需要并滚动它)。如果有人有更好的方法来完成我想要做的事情,我就是为了它(再次,我希望能够在XAML中进行实际绑定, 不在后面的代码中

我的问题

问题是我的类型比较失败(即使我看到调试我看到PropertyType是ICommand类型)。当我使用is关键字时,PropertyType与ICommand相比总是返回false,而且对Linq法术的任何尝试(例如e.Property.PropertyType.GetInterfaces( ).Any( i => i.IsGenericType && i.GetGenericTypeDefinition( ) == typeof( ICommand ) ))都会失败。

因此,如果某人有更好的方法,我会全力以赴,但就目前而言 - 为什么我的类型比较失败如此之难?

1 个答案:

答案 0 :(得分:2)

e.PropertyTypeType,而不是该类型的实例,因此与&#34;进行比较是&#34;不管用。你需要的是(例如):

typeof(ICommand).IsAssignableFrom(e.Property.PropertyType)