- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想知道是否有人对解决以下设计问题有好的建议/模式。我有一个命令类的层次结构。在最抽象的层面上,我有一个 ICommand 接口(interface)。执行 ICommand 的 RunCommand() 函数的结果是一个对象。不同的命令将有不同的结果类型,因此这是一个适当的抽象。
进一步构建层次结构,使用泛型变得可取。我创建了一个 Generic.ICommand(Of TResult) 接口(interface)。
有一些常见的样板代码,如 Run、TryRun、BeginRun、BeginTryRun 等,我需要所有命令 - 所以我创建了一个 BaseCommand 类来提供所有这些,并实现了非通用 ICommand 接口(interface)。然而,BaseCommand 不知道如何实际执行任何操作,因此所有这些命令最终都会调用一个名为 InternalRunCommand 的 protected 抽象函数。这一切都很好。
现在我想创建该类的通用版本:BaseCommand(Of T)。它继承自 BaseCommand 并且还实现了通用 ICommand(Of T) 接口(interface)。这行得通,但现在存在差异:InternalRunCommand。
在非通用版本中,InternalRunCommand 返回一个对象。在我的通用 BaseCommand(Of T) 类中,我想用一个通用版本重载它,该版本将结果作为类型 T 返回。不幸的是,VB.NET/C# 编译器不允许您提供方法重载,其中唯一的区别是返回类型。
由于这是一个 protected 函数,它最终不会对整个 API 产生太大影响,但它仍然让我恼火,因为我没有针对这一点架构的美观解决方案。
目前我已经覆盖了 BaseCommand(Of T) 类中的非泛型 InternalRunCommand,以便它调用一个新的 protected 抽象 OnRunCommand 函数,该函数采用相同的参数但返回类型 T 的结果。InternalRunCommand 具有也被声明为 NonOverridable。这可能是我能得到的最接近的 - 但想看看是否有更好的想法? :)
编辑:我已按要求包含了代码的简化副本,以便您可以更好地想象问题:
Public Interface ICommand
Property Name as String
Property Description As String
Property ResultType as Type
Function RunCommand(target as Device) As Object
Function TryRunCommand(target as Device, Byref result as Object) AS Boolean
Function BeginRunCommand(target as Device) as Task(Of Object)
Function BeginTryRunCommand(target as Device) As Task(of Boolean)
End Interface
Namespace Generic
Public Interface ICommand(Of TResult)
Function RunCommand(target as Device) as T
Function BeginRunCommand(target as Device) As Task(Of T)
End Interface
End Namespace
Public MustInherit Class BaseCommand
Implements ICommand
Public Function RunCommand(target as Device) As Object Implements ICommand.RunCommand
Return InternalRunCommand(device)
End Function
Public Function BeginRunCommand(target as Device) As Task(of Object) Implements ICommand.BeginRunCommand
Return Task(Of Object).Factory.StartNew( Function() InternalRunCommand(target))
End Function
' Other boiler plate code goes here'
Protected MustOverride Function InternalRunCommand(target as Device) As Object
End Class
Namespace Generic
Public Class BaseCommand(Of TResult)
Inherits BaseCommand
Implements ICommand(Of TResult)
Public Function BeginRunCommand(target as Device) As Task(of TResult) Implements ICommand(Of TResult).BeginRunCommand
Return Task(Of TResult).Factory.StartNew( Function() OnRunCommand(target))
End Function
Protected NotOverridable Overrides Function InternalRunCommand(target as Device) As Object
' Re-route to the generic version'
Return OnRunCommand(device)
End Function
Protected MustOverride Function OnRunCommand(target as Device) As T
End Class
最佳答案
我想我已经找到了一个很好的模式,它允许您使用通用函数覆盖此类函数的非通用版本,并且没有像我在 OP 中那样的任何困惑的包装函数。
我已将 protected 抽象 InnerRunCommand 函数替换为同名的 protected ReadOnly 属性。此属性的类型是 Func(Of ICommand, Device, Object)。我修改了 BaseCommand 类的构造函数以接受这样一个 Func 对象。
在 Generic.BaseCommand(Of T) 类中,我可以使用 Func(Of ICommand, Device, T) 类型的类似属性隐藏 InnerRunCommand。 Generic.BaseCommand(Of T) 的构造函数同样接受这样一个 Func 对象,并将该对象毫无问题地传递回非泛型 BaseCommand 构造函数:)
我正在修改我的架构以支持这种新模式,如果我遇到任何问题,我会告诉大家。我欢迎对这种方法的任何批评,并欢迎其他答案:)
编辑:我在下面构造了一个建议模式的简单示例。我用 C# 而不是 VB.NET 编写了它。在 C# 中转换 FUNC 对象涉及更多的工作(VB.NET 在幕后为您处理)。然而,在这两种语言中,这些匿名函数的使用保持了 API 的清洁和可扩展性。
public interface ICommand
{
object Execute();
Boolean TryExecute(out object result);
Task<object> BeginExecute();
}
namespace Generic
{
public interface ICommand<TResult> : ICommand
{
new TResult Execute();
Boolean TryExecute(out TResult result);
new Task<TResult> BeginExecute();
}
}
public class Command : ICommand
{
private Func<ICommand, object> _execFunc = null;
protected Func<ICommand, object> ExecFunc { get { return _execFunc; } }
public Task<object> BeginExecute()
{
return Task<object>.Factory.StartNew(() => _execFunc(this) );
}
public object Execute()
{
return _execFunc(this);
}
public bool TryExecute(out object result)
{
try
{
result = _execFunc(this);
return true;
}
catch(Exception ex)
{
result = null;
return false;
}
}
public Command (Func<ICommand, object> execFunc)
{
if (execFunc == null) throw new ArgumentNullException("execFunc");
_execFunc = execFunc;
}
}
namespace Generic
{
public class Command<TResult> : Command, ICommand<TResult> where TResult : class
{
new protected Func<ICommand<TResult>, TResult> ExecFunc => (ICommand<TResult> cmd) => (TResult)base.ExecFunc(cmd);
public bool TryExecute(out TResult result)
{
try
{
result = ExecFunc(this);
return true;
}
catch(Exception ex)
{
result = null;
return false;
}
}
Task<TResult> ICommand<TResult>.BeginExecute()
{
return Task<TResult>.Factory.StartNew(() => ExecFunc(this) );
}
TResult ICommand<TResult>.Execute()
{
return ExecFunc(this);
}
public Command(Func<ICommand<TResult>, TResult> execFunc) : base((ICommand c) => (object)execFunc((ICommand<TResult>)c))
{
}
}
}
public class ConcatCommand : Generic.Command<string>
{
private IEnumerable<string> _inputs;
public IEnumerable<String> Inputs => _inputs;
public ConcatCommand(IEnumerable<String> inputs) : base( (Generic.ICommand<string> c) => (string)String.Concat(((ConcatCommand)c).Inputs) )
{
if (inputs == null) throw new ArgumentNullException("inputs");
_inputs = inputs;
}
}
class Program
{
static void Main(string[] args)
{
string[] inputs = { "This", " is ", " a ", " very ", " fine ", " wine!" };
ICommand c = new ConcatCommand(inputs );
string results = (string)c.Execute();
Console.WriteLine(results);
Console.ReadLine();
}
}
关于c# - 泛型基类覆盖非泛型基类函数模式? (。网),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52846094/
我知道 C++ 中的 overriding 是什么。但是,是否存在覆盖?如果有,是什么意思? 谢谢。 最佳答案 在 C++ 术语中,您有 覆盖(与类层次结构中的虚拟方法相关)和 重载(与具有相同名称但
我想捕获位于另一个元素下的元素的鼠标事件。 这是我所拥有的示例:http://jsfiddle.net/KVLkp/13/ 现在我想要的是当鼠标悬停在红色方 block 上时蓝色方 block 有黄色
以下报道 here我尝试创建一个带有重叠散点图的箱线图。 但是当我运行时: In [27]: table1.t_in[table1.duration==6] Out[27]: counter 7
有一个 JS Fiddle here , 你能在不克隆到新对象的情况下替换 e.target 吗? 下面重复了那个 fiddle 的听众; one.addEventListener('click',
首先要解决重复的可能性: 我不是询问 Override 是什么、它的含义或 @Override 在 java 文档注释之外。那是我不是问 /**Some JavaDoc Comment*/ @over
我想要高于定义的数组。它存储点及其坐标。 public static List simpleGraph(List nodes) { int numEdges = nodes.size() *
我在 http://olisan.dk/blog/ 有一个博客- 如您所见,有一个 28 像素的高间隙(边距顶部)...在 style.css 中: margin-top: 0; 也被设置为 marg
Vulkan 句柄是指向 struct 的不透明指针,或者只是无符号的 64 位整数,具体取决于 VK_USE_64_BIT_PTR_DEFINES 的值: #if (VK_USE_64_BI
我正在尝试提供一个行为类似于 DataGridTextColumn 的 DataGrid 列,但在编辑模式下有一个附加按钮。我查看了 DataGridTemplateColumn,但似乎更容易将 Da
使用 Django 1.10 我想在用户名中允许\字符,因为我在使用“django.contrib.auth.middleware.RemoteUserMiddleware”的 Windows 环境中
我正在尝试使用 ffmpeg 将 Logo 放入 rtmp 流中。我的 ffmpeg 版本是 ffmpeg version 4.3.1目前在我的复杂过滤器中,我有: ffmpeg -re -i 'v
是否有用于Firebase 3存储的方法/规则来禁用文件更新或覆盖? 我为数据库找到了data.exists(),但没有为存储找到解决方案。 最佳答案 TL; DR:在Storage Security
我有两个 Docker Compose 文件,docker-compose.yml看起来像这样 version: '2' services: mongo: image: mongo:3.2
我需要覆盖 JPA 中的集合表吗?也许有人有想法 public class nationality{ @Embedded @AttributeOverrides({
嗨,我正在使用 WIX 和下面的代码将文件安装到目录中。 我的应用程序的工作方式是用户可以在该目录中复制他们自己的文件,覆盖他们喜欢的内容
我正在尝试为 Lua 中的字符串实现我自己的长度方法。 我已成功覆盖字符串的 len() 方法,但我不知道如何为 # 运算符执行此操作。 orig_len = string.len function
在Scala 2.10.4中,给出以下类: scala> class Foo { | val x = true | val f = if (x) 100 else 200
我想做上面的事情。 我过去覆盖了许多文件...... block ,模型,助手......但这个让我望而却步。 谁能看到我在这里做错了什么: (我编辑了这段代码......现在包括一些建议......
根据javadoc An instance method in a subclass with the same signature (name, plus the number and the ty
我有一段代码,只要有可用的新数据作为 InputStream 就会生成新数据。每次都覆盖同一个文件。有时文件在写入之前变为 0 kb。 Web 服务会定期读取这些文件。我需要避免文件为 0 字节的情况
我是一名优秀的程序员,十分优秀!