gpt4 book ai didi

c# - 泛型类约束,其中 是约束泛型类的类型

转载 作者:行者123 更新时间:2023-11-30 17:36:30 24 4
gpt4 key购买 nike

也许不是最准确的标题,但有点难以描述;也许你们可以帮我解决这个问题?我正在使用 MVC 格式编写游戏,我希望每个基类( Controller 、模型和 View )都引用它们的附带功能,形成一种三角形(即模型引用 Controller 定义它,以及引用它的 View 等。)这些类中的大部分看起来像这样:

public class Model {
public Controller controller;
public View view;

public void Connect (Controller controller, View view) {
this.controller = controller;
this.view = view;
}
}

这没问题,但每当我打算启动 ChildModel 的 Controller 时,我都需要转换为适当的 ChildController 以获得正确的版本。我可以制作一个实用程序方法/getter 来获取适当转换的项目,但我不想为每个子类重写这段代码。我以为我可以通过使基类通用化来解决这个问题,但现在我遇到了一个问题,新的通用类需要引用试图定义它们的类,因此:

public class Model<V, C> where V : View<?, C> where C : Controller<?, V> {
public Controller<?, V> controller;
public View<?, C> view;

public void Connect (Controller<?, V> controller, View<?, C> view) {
this.controller = controller;
this.view = view;
}
}

如您所见,这在基类中很快就会变得困惑。我不知道要为试图定义约束的模型放置什么符号(引用上面的示例)。将“模型”放入问号似乎也无法编译,因为我遇到了一个 hell 般的装箱转换问题。

有没有一种方法可以完成我所追求的,或者我只是想在这里变得太聪明?如果这行得通,我希望能够声明子类的类型受限于它们的“三角形”,这样我就可以避免不必要的强制转换或辅助方法:

public class ChildModel<ChildView, ChildController> {

public ChildModel () {
this.controller <- calls ChildController type, not base type!
}
}

有人有什么想法吗?

最佳答案

您似乎混淆了所有权和交互。所有权意味着一个人拥有另一个人,而互动则意味着他们如何相互交流。 MVC 主要定义三个参与者之间的交互,尽管您可以说 View 和 Controller 都拥有一个模型。

enter image description here

在您显示的代码中,一个类拥有一个属性,因此 Controller 类拥有一个 View ,而一个 View 拥有一个 Controller 。

var model = new Model();
var view = new View<Controller<Model, View<Controller, Model>, ...

这不适用于泛型,因为交互变成了循环。这是鸡和蛋的问题:鸡来自鸡下的蛋。我们可以通过为 Controller 提供 View 的所有权以及模型的 Controller 和 View 所有权来解决大部分问题。

public class Model
{
}

public interface IView<M>
{
M Model { get; }
}

public class MyView : IView<Model>
{
public MyView(Model model)
{
Model = model;
}

public Model Model
{
get;
}
}

public interface IController<V, M>
{
M Model { get; }
V View { get; }
}

public class MyController : IController<MyView, Model>
{
public MyController(MyView view, Model model)
{
View = view;
Model = model;
}

public Model Model
{
get;
}

public MyView View
{
get;
}
}

我们仍然使用泛型来做到这一点,并且您可以轻松访问到目前为止的大部分信息,而无需引入循环引用。

class Program
{
public static void Main()
{
var model = new Model();
var view = new MyView(model);
var controller = new MyController(view, model);
}
}

现在,如果您想确保 View 具有对 Controller 的引用,您可以通过属性来实现。

view.Controller = controller;

您可以无视我刚刚向您展示的所有内容 - 并走属性注入(inject)路线。这意味着您可以简单地执行此操作,而不是通过构造函数获取依赖项,这会对如何创建对象产生循环引用限制。

var model = new Model();
var view = new View();
var controller = new Controller();

model.View = view;
model.Controller = controller;

view.Controller = controller;
view.Model = model;

controller.View = view;
controller.Model = model;

无论您使用什么方法,诀窍都是避免您当前代码中存在的循环依赖问题。大多数 MVC 框架都提供了丰富的数据绑定(bind),打破了类之间的直接耦合,但如果您没有,则必须编写一些东西或找到一些东西,或者在语言规则的范围内工作。

有很多方法可以解决这个问题。在我写这篇文章时,发布了另一个答案,因此您也应该看看它。

关于c# - 泛型类约束,其中 <T> 是约束泛型类的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39481881/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com