如何在C#中推广代理?

时间:2016-02-23 03:24:18

标签: c# delegates

我正在尝试创建一个类似于以下的委托序列构建器(这对于单元测试中的存根很有用):

    public class StubSequenceBuilder<T>
    {
        private readonly Queue<Func<T>> _sequenceQueue = new Queue<Func<T>>();

        public StubSequenceBuilder<T> Next(Func<T> func)
        {
            _sequenceQueue.Enqueue(func);
            return this;
        }

        public Func<T> Build()
        {
            return () =>
            {
                var func = _sequenceQueue.Dequeue();
                return func();
            };
        } 
    }

序列构建器创建一个Func<T>,每次调用它时都返回一个不同的值。

但是,这仅适用于没有参数且返回值的委托。有没有办法概括这个类来支持任何委托?

我知道类型约束不支持委托; C#中还有什么可以用来实现这个目标吗?

1 个答案:

答案 0 :(得分:0)

C#中没有任何内容可以实现这一点但你可以使用类似下面的文本模板(* .tt):

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ output extension=".cs" #>

using System;
using System.Linq;
using System.Collections.Generic;

<#

var maxArguments = 5;

for(int i=0; i < maxArguments; ++i) {

    var argTypes = string.Join(", ",new string[i+1].Select((x,j)=>"T"+j).ToArray());
#>

public class StubSequenceBuilder<<#= argTypes #>>
{
    private readonly Queue<Func<<#= argTypes #>>> _sequenceQueue = new Queue<Func<<#= argTypes #>>>();

    public StubSequenceBuilder<<#= argTypes #>> Next(Func<<#= argTypes #>> func)
    {
        _sequenceQueue.Enqueue(func);
        return this;
    }


    //...
}

<# } #>

输出(* .cs):

using System;
using System.Linq;
using System.Collections.Generic;

public class StubSequenceBuilder<T0>
{
    private readonly Queue<Func<T0>> _sequenceQueue = new Queue<Func<T0>>();

    public StubSequenceBuilder<T0> Next(Func<T0> func)
    {
        _sequenceQueue.Enqueue(func);
        return this;
    }


    //...
}

public class StubSequenceBuilder<T0, T1>
{
    private readonly Queue<Func<T0, T1>> _sequenceQueue = new Queue<Func<T0, T1>>();

    public StubSequenceBuilder<T0, T1> Next(Func<T0, T1> func)
    {
        _sequenceQueue.Enqueue(func);
        return this;
    }


    //...
}

//...