Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 存储不同泛型类型的列表_C#_Generics_Tpl Dataflow - Fatal编程技术网

C# 存储不同泛型类型的列表

C# 存储不同泛型类型的列表,c#,generics,tpl-dataflow,C#,Generics,Tpl Dataflow,我知道这是一个经常讨论的话题,因为我发现很多帖子都在谈论它。不幸的是,它们似乎都没有解决我的问题,要么是因为我不理解解决方案,要么是因为我把我的问题复杂化了 我在现有的TPL数据流库的基础上实现了一个简单的数据流。为了便于测试,我想向其构造函数提供一个块连接列表,以便它自动创建所有块及其连接。为此,我创建了以下类: internal class DataflowBlockConnection<TInput, TOutput> : IDataflowBlockConnection {

我知道这是一个经常讨论的话题,因为我发现很多帖子都在谈论它。不幸的是,它们似乎都没有解决我的问题,要么是因为我不理解解决方案,要么是因为我把我的问题复杂化了

我在现有的TPL数据流库的基础上实现了一个简单的数据流。为了便于测试,我想向其构造函数提供一个块连接列表,以便它自动创建所有块及其连接。为此,我创建了以下类:

internal class DataflowBlockConnection<TInput, TOutput> : IDataflowBlockConnection
{
    public ISourceBlock<TOutput> Source { get; set; }
    public ITargetBlock<TInput> Target { get; set; }
}
不幸的是,这不会编译,因为我在接口中没有关于源和目标的信息,这将允许我将源连接到目标。这就是其他线程与此不同的地方。通过这种设计,我可以拥有一个具有自己输入和输出类型的不同连接的列表,但我无法访问每个块,因为我需要关于TInput和TOutput的信息。我错过什么了吗

编辑:

在@Enigmativity的评论之后,我减少了我的问题,以便更容易理解

我有两种类型的类,源块和目标块。它们都实现IDataflowBlock接口,因为它们都是不同类型的块。它们都接收一个泛型类型(TInput或TOutput),可以是任何类型

源块可以链接到目标块,但该方法仅适用于源块

以下是简化类(这是TPL数据流的一个简短转录,仅基于我的问题):

为了能够从IDataflowBlockConnection访问源和目标,而无需将TInput和TOutput关联到它(这会破坏具有不同TInput和TOutput类型的列表的可能性),我将其更改为:

internal interface IDataflowBlockConnection
{
    ISourceBlock<TOutput> GetSource<TOutput>();
    ITargetBlock<TInput> GetTarget<TInput>();
}
内部接口IDataflowBlockConnection
{
ISourceBlock GetSource();
ITargetBlock GetTarget();
}


现在我正在考虑用反射调用这些方法,这(我认为,因为尚未实现)将解决我的问题。我的问题是:我是否使解决方案复杂化了?有没有一个优雅的解决方案是我没有看到的?

我在寻找解决问题的方法时,无意中发现了UppDynamic。一种解决方案是使用反射在运行时将类型注入方法,正如@Theodor Zoulias所建议的那样。另一个解决方案是使用动态,尽管这仍然是一个有争议的话题,因为它取决于具体情况。这是一个好方法吗?

我无意中发现了UppDynamic,正在寻找解决问题的方法。一种解决方案是使用反射在运行时将类型注入方法,正如@Theodor Zoulias所建议的那样。另一个解决方案是使用动态,尽管这仍然是一个有争议的话题,因为它取决于具体情况。这个好用吗?

我承认我已经有一段时间没看这个东西了,所以我可能遗漏了什么。你的界面可以是通用的吗
IDataflowBlockConnection
?如果我的接口是泛型接口,则会强制TInput或TOutput的值在其整个生命周期内保持不变,这意味着我失去了拥有多类型列表的能力:/这是使用反射的选项吗?当然,这是使用反射的选项。我想避免它,但如果考虑到目前的情况,这是最好的选择,它很好,我认为不经过思考是不可能的,因为块实现的唯一非通用接口是,它不支持将它们链接到其他块。我承认我已经有一段时间没有研究过这些东西了,所以我可能错过了什么。你的界面可以是通用的吗
IDataflowBlockConnection
?如果我的接口是泛型接口,则会强制TInput或TOutput的值在其整个生命周期内保持不变,这意味着我失去了拥有多类型列表的能力:/这是使用反射的选项吗?当然,这是使用反射的选项。我想避免它,但如果考虑到具体情况,它是最好的选择,我认为不经过思考是不可能的,因为块实现的唯一非通用接口是,它不支持将它们链接到其他块。
dynamic
在处理外部对象(如XML、JSON或DBs)时很好,这些对象的名称不断变化。你在对付C。处理C#几乎总是有比动态更好的方法。那么,你对我的问题有什么建议呢?我很想给你一个答案,但问题还不完整。我看不到块连接列表的定义。我没有看到任何构造函数。我不知道什么
CreateStructure
被覆盖,从哪里覆盖。我没有看到
ConnectBlocks
。你能提供一个完整的,我可以复制,粘贴,并看到在我的环境中没有编译的代码。然后我可以重构并使其工作。然后我可以给你一个答案。你没有其他答案的原因是这个问题不完整。你能帮我吗?我更新了我的问题,所以它提供了更多的细节。我希望它是有帮助的:)
dynamic
在处理外部对象(如XML、JSON或DBs)时很好,这些对象的名称不断变化。你在对付C。处理C#几乎总是有比动态更好的方法。那么,你对我的问题有什么建议呢?我很想给你一个答案,但问题还不完整。我看不到块连接列表的定义。我没有看到任何构造函数。我不知道什么
CreateStructure
被覆盖,从哪里覆盖。我没有看到
ConnectBlocks
。你能提供一个完整的,我可以复制,粘贴,并看到在我的环境中没有编译的代码。然后我可以重构并使其工作。然后我可以给你一个答案。你没有其他答案的原因是因为这个问题
internal interface IDataflowBlock
{

}

internal interface ISourceBlock<out TOutput> : IDataflowBlock
{
    void LinkTo(ITargetBlock<TOutput> target);
}

internal interface ITargetBlock<in TInput> : IDataflowBlock
{

}
internal interface IDataflowBlockConnection
{

}

internal class DataflowBlockConnection<TInput, TOutput> : IDataflowBlockConnection
{
    public ISourceBlock<TOutput> Source { get; set; }
    public ITargetBlock<TInput> Target { get; set; }
}
// Two blocks that act as source, consuming types int and char
        ISourceBlock<int> sourceInt = new SourceBlock<int>();
        ISourceBlock<char> sourceChar = new SourceBlock<char>();

        // One block that acts as target, receiving type string
        ITargetBlock<string> targetString = new TargetBlock<string>();

        // Pipeline structure:
        // sourceInt -> targetString
        // sourceChar -> targetString

        DataflowBlockConnection<string, int> connection1 = new DataflowBlockConnection<string, int>
        {
            Source = sourceInt,
            Target = targetString
        };

        DataflowBlockConnection<string, char> connection2 = new DataflowBlockConnection<string, char>
        {
            Source = sourceChar,
            Target = targetString
        };

        List<IDataflowBlockConnection> blockConnections = new List<IDataflowBlockConnection>
        {
            connection1, connection2
        };
foreach (IDataflowBlockConnection connection in blockConnections)
        {
            // Does not compile, since IDataflowBlockConnection has no information about Source and Target.
            connection.Source.LinkTo(Target);
        }
internal interface IDataflowBlockConnection
{
    ISourceBlock<TOutput> GetSource<TOutput>();
    ITargetBlock<TInput> GetTarget<TInput>();
}