能够使用和不使用泛型创建类实例

问题描述 投票:0回答:2

我有一个关于c#中的泛型的问题我希望创建可以使用泛型类型调用的命令类,而不需要它:

public class Command : ICommand
{
    private readonly Action<object> execute;

    private readonly Predicate<object> canExecute;

    private readonly Action<TClass> tExecute;

    private readonly Predicate<TClass> tCanExecute;

    public Command(Action<object> execute, Predicate<object> canExecute = null)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }

    public Command(Action<TClass> execute, Predicate<TClass> canExecute = null)
    {
        tExecute = execute;
        tCanExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return this.canExecute == null || (this.canExecute != null && this.canExecute(parameter));
    }

    public bool CanExecute<TClass>(TClass parameter)
    {
        return canExecute == null || (canExecute != null && canExecute(parameter));
    }

    public void Execute(object parameter)
    {
        this.execute(parameter);
    }

    public void Execute<TClass>(TClass parameter)
    {
        execute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }
}

所以我可以这样使用:

new Command(p => some instructions);

要么

new Command<Class> (p => some instructions p.property)

问题是在这种情况下类实例总是需要<>中的泛型类型,并且我知道我可以将p转换为某些类型,如(Class)p,但只是想知道这是否可行?

c#
2个回答
1
投票

问题不在于创建通用实例 - 因为你总是可以这样做 - 但是你将如何统一操作命令。您是否能够使用一个命令特定于某些类型T的事实。

为了实现这一点,你将在某些时候不得不贬低一些东西。我不知道任何设计没有贬低。

所以,这个过程就像坚持使用ICommand界面,后者对泛型一无所知。它的ExecuteCanExecute将是所有呼叫者可用的唯一公共接口,他们只会收到object

interface ICommand
{
    bool CanExecute(object param);
    void Execute(object param);
}

然后,在通用的Command<T>中,你可以拥有接受T的强类型变体,你会贬低param

class Command<T> : ICommand
{
    public bool CanExecute(object param) =>
        this.CanExecute(param as T);

    public void Execute(object param) =>
        this.Execute(param as T);

    public bool CanExecute(T param) { ... }
    public void Execute(T param) { ... }
}

而那就是麻烦将从你身上开始的地方。在给定T实例的情况下,您能保证参数的类型为ICommand吗?如果可以,那你就没事了。否则,你会有一个设计缺陷。

还要注意,在这个解决方案中,我将Command类绑定到泛型参数,而不仅仅是它的一个方法。如果你只留下CanExecuteExecute方法泛型,那么我预计后来会出现大问题 - 这类课程的覆盖面太大了。使用通用命令,您可以自由地引入抽象的Command<T>或接口ICommand<T>,然后为某些特定类型T构建特殊命令,如:

class SaveCommand : ICommand<Document> { }
class CreateDirectory : ICommand<DirectoryInfo> { }
...

0
投票

我认为,您可以将Command <T>类作为基础并重新定义

class Command : Command<Object> {} 

用作非泛型的。

© www.soinside.com 2019 - 2024. All rights reserved.