创建一个函数,连接两个数据流节点,这些节点具有存储在通用列表中的不同类型
Create a function that connects two Dataflow nodes with different types stored in a generic list
我正在尝试使用 C# 和数据流制作一个基于节点的编辑器。我为节点创建了以下 class:
public interface INode
{
public int Id {get; set;}
public string Name {get; set;}
}
public class Node<TInput, TOutput> : INode
{
public string Name {get; private set;}
public int Id {get; set;}
public IPropagatorBlock<TInput, TOutput> NodeBlock {get; protected set;}
public Node(string Name, int Id) {
this.Name = Name;
this.Id = Id;
}
}
然后我有从 class 节点派生的 classes:
public class ThresholdNode : Node<int, float>
{
public ThresholdNode(string Name, int Id) : base(Name, Id)
{
NodeBlock = CreateNodeBlock();
}
private IPropagatorBlock<int, float> CreateNodeBlock() {
return new TransformBlock<int, float>(...);
}
}
然后是节点管理器,负责管理节点。节点管理器将所有创建的节点存储在以下通用列表中:
public List<INode> NodeList
由于节点可以有不同的输入和输出类型,我不能将 NodeBlock 放在 INode
接口中。所以这就是我被困的地方。我想在连接两个节点的 NodeManager class 中创建一个函数。如果我知道它们的类型,我可以执行以下操作:
public void ConnectNodes(int originIndex, int destinationIndex) {
var originNodeBlock = NodeList[originIndex] as IPropagatorBlock<int, float>;
var destinationNodeBlock = NodeList[destinationIndex] as IPropagatorBlock<float, string>
originNodeBlock.LinkTo(destinationNodeBlock);
}
但是因为我不知道它们的输入和输出是什么类型,所以我不能转换它们。我也尝试使用 dynamic
来做到这一点,但它在运行时抛出了一个异常,我相信它与数据流有关,尽管我想被证明是错误的。这是我尝试使用 dynamic
:
的方法
首先,我在 NodeClass 上为 return NodeBlock 创建了一个方法,并将相同的方法添加到 INode 接口:
public interface INode {
...
public dynamic GetNodeBlock();
}
public class Node<TInput, TOutput> : INode {
...
public dynamic GetNodeBlock() {
return this.NodeBlock;
}
}
然后,在 NodeManager class 中,我编写了以下连接节点的方法:
public bool ConnectNodes(int originIndex, int destinationIndex) {
INode originNode = NodeList[originIndex];
INode destinationNode = NodeList[destinationIndex];
var originNodeBlock = originNode.GetNodeBlock();
var destinationNodeBlock = originNode.GetNodeBlock();
originNodeBlock.LinkTo(destinationNodeBlock); // <--- throws exception here
return true;
}
但是,在运行时 LinkTo 抛出以下异常:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'No overload for method 'LinkTo' takes 1 arguments'
您要查找的 LinkTo
的特定重载实现为 Extension Method. You can find this detail from the documentation for IPropagatorBlock。
不幸的是,the dynamic
keyword and Extension method syntax don't work as you would like。 IPropagatorBlock
确实定义了一个带有两个参数的 LinkTo
方法,但是找不到您尝试使用的只有一个参数的方法。上面 link 中的另一个答案进一步解释了 为什么 dynamic
和扩展方法效果不佳。
正如 linked 的回答所说,您仍然可以将扩展方法与 dynamic
一起使用,但您必须将其作为 static
方法调用并传入两个参数。在您的情况下,带有异常的行变为:
DataflowBlock.LinkTo(originNodeBlock, destinationNodeBlock);
(如果您还没有,请不要忘记 using System.Threading.Tasks.Dataflow;
。)
P.S。既然你说你是初学者,我建议你尽可能避免使用 dynamic
。请参阅 以了解有关原因的一些讨论以及一些设计替代方案。
我正在尝试使用 C# 和数据流制作一个基于节点的编辑器。我为节点创建了以下 class:
public interface INode
{
public int Id {get; set;}
public string Name {get; set;}
}
public class Node<TInput, TOutput> : INode
{
public string Name {get; private set;}
public int Id {get; set;}
public IPropagatorBlock<TInput, TOutput> NodeBlock {get; protected set;}
public Node(string Name, int Id) {
this.Name = Name;
this.Id = Id;
}
}
然后我有从 class 节点派生的 classes:
public class ThresholdNode : Node<int, float>
{
public ThresholdNode(string Name, int Id) : base(Name, Id)
{
NodeBlock = CreateNodeBlock();
}
private IPropagatorBlock<int, float> CreateNodeBlock() {
return new TransformBlock<int, float>(...);
}
}
然后是节点管理器,负责管理节点。节点管理器将所有创建的节点存储在以下通用列表中:
public List<INode> NodeList
由于节点可以有不同的输入和输出类型,我不能将 NodeBlock 放在 INode
接口中。所以这就是我被困的地方。我想在连接两个节点的 NodeManager class 中创建一个函数。如果我知道它们的类型,我可以执行以下操作:
public void ConnectNodes(int originIndex, int destinationIndex) {
var originNodeBlock = NodeList[originIndex] as IPropagatorBlock<int, float>;
var destinationNodeBlock = NodeList[destinationIndex] as IPropagatorBlock<float, string>
originNodeBlock.LinkTo(destinationNodeBlock);
}
但是因为我不知道它们的输入和输出是什么类型,所以我不能转换它们。我也尝试使用 dynamic
来做到这一点,但它在运行时抛出了一个异常,我相信它与数据流有关,尽管我想被证明是错误的。这是我尝试使用 dynamic
:
首先,我在 NodeClass 上为 return NodeBlock 创建了一个方法,并将相同的方法添加到 INode 接口:
public interface INode {
...
public dynamic GetNodeBlock();
}
public class Node<TInput, TOutput> : INode {
...
public dynamic GetNodeBlock() {
return this.NodeBlock;
}
}
然后,在 NodeManager class 中,我编写了以下连接节点的方法:
public bool ConnectNodes(int originIndex, int destinationIndex) {
INode originNode = NodeList[originIndex];
INode destinationNode = NodeList[destinationIndex];
var originNodeBlock = originNode.GetNodeBlock();
var destinationNodeBlock = originNode.GetNodeBlock();
originNodeBlock.LinkTo(destinationNodeBlock); // <--- throws exception here
return true;
}
但是,在运行时 LinkTo 抛出以下异常:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'No overload for method 'LinkTo' takes 1 arguments'
您要查找的 LinkTo
的特定重载实现为 Extension Method. You can find this detail from the documentation for IPropagatorBlock。
不幸的是,the dynamic
keyword and Extension method syntax don't work as you would like。 IPropagatorBlock
确实定义了一个带有两个参数的 LinkTo
方法,但是找不到您尝试使用的只有一个参数的方法。上面 link 中的另一个答案进一步解释了 为什么 dynamic
和扩展方法效果不佳。
正如 linked 的回答所说,您仍然可以将扩展方法与 dynamic
一起使用,但您必须将其作为 static
方法调用并传入两个参数。在您的情况下,带有异常的行变为:
DataflowBlock.LinkTo(originNodeBlock, destinationNodeBlock);
(如果您还没有,请不要忘记 using System.Threading.Tasks.Dataflow;
。)
P.S。既然你说你是初学者,我建议你尽可能避免使用 dynamic
。请参阅