sách gpt4 ăn đã đi

c# - 泛型基类覆盖非泛型基类函数模式? (。网)

In lại Tác giả: Walker 123 更新时间:2023-11-30 18:13:21 31 4
mua khóa gpt4 giày nike

我想知道是否有人对解决以下设计问题有好的建议/模式。我有一个命令类的层次结构。在最抽象的层面上,我有一个 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

câu trả lời hay nhất

我想我已经找到了一个很好的模式,它允许您使用通用函数覆盖此类函数的非通用版本,并且没有像我在 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 BeginExecute();
}

namespace Generic
{
public interface ICommand : ICommand
{
new TResult Execute();
Boolean TryExecute(out TResult result);
new Task BeginExecute();
}
}

public class Command : ICommand
{
private Func _execFunc = null;
protected Func ExecFunc { get { return _execFunc; } }

public Task BeginExecute()
{
return Task.Factory.StartNew(() => _execFunc(this) );
}

public object Execute()
{
return _execFunc(this);
}

public bool TryExecute(out object result)
{
thử
{
result = _execFunc(this);
trả về giá trị đúng;
}
catch(Ngoại lệ ex)
{
result = null;
trả về false;
}
}

public Command (Func execFunc)
{
if (execFunc == null) throw new ArgumentNullException("execFunc");
_execFunc = execFunc;
}
}

namespace Generic
{
public class Command : Command, ICommand where TResult : class
{
new protected Func<>, TResult> ExecFunc => (ICommand cmd) => (TResult)base.ExecFunc(cmd);

public bool TryExecute(out TResult result)
{
thử
{
result = ExecFunc(this);
trả về giá trị đúng;
}
catch(Ngoại lệ ex)
{
result = null;
trả về false;
}
}

Task ICommand.BeginExecute()
{
return Task.Factory.StartNew(() => ExecFunc(this) );
}

TResult ICommand.Execute()
{
return ExecFunc(this);
}

public Command(Func<>, TResult> execFunc) : base((ICommand c) => (object)execFunc((ICommand)c))
{
}
}
}

public class ConcatCommand : Generic.Command
{
private IEnumerable _inputs;
public IEnumerable Inputs => _inputs;

public ConcatCommand(IEnumerable inputs) : base( (Generic.ICommand 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/

31 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress