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

时间:2018-02-28 08:30:34

标签: c#

我有一个关于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)

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

2 个答案:

答案 0 :(得分: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> { }
...

答案 1 :(得分:0)

我想,你可以制作Command&lt; T&gt; class as base and redefine

class Command : Command<Object> {} 

用作非泛型。