我有一个关于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,但只是想知道这是否可行?
问题不在于创建通用实例 - 因为你总是可以这样做 - 但是你将如何统一操作命令。您是否能够使用一个命令特定于某些类型T的事实。
为了实现这一点,你将在某些时候不得不贬低一些东西。我不知道任何设计没有贬低。
所以,这个过程就像坚持使用ICommand
界面,后者对泛型一无所知。它的Execute
和CanExecute
将是所有呼叫者可用的唯一公共接口,他们只会收到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
类绑定到泛型参数,而不仅仅是它的一个方法。如果你只留下CanExecute
和Execute
方法泛型,那么我预计后来会出现大问题 - 这类课程的覆盖面太大了。使用通用命令,您可以自由地引入抽象的Command<T>
或接口ICommand<T>
,然后为某些特定类型T
构建特殊命令,如:
class SaveCommand : ICommand<Document> { }
class CreateDirectory : ICommand<DirectoryInfo> { }
...
我认为,您可以将Command <T>类作为基础并重新定义
class Command : Command<Object> {}
用作非泛型的。