C# 具有5+;参数和访问调用参数

C# 具有5+;参数和访问调用参数,c#,moq,delegates,action,C#,Moq,Delegates,Action,我有一个函数,我想要Moq。问题是它需要5个参数。该框架仅包含Action和Moq的genericCallBack()仅重载Action和四个generic版本。有没有一个优雅的解决办法 这就是我想做的: public class Filter : IFilter { public int Filter(int i1, int i2, int i3, int i4, int i5){return 0;} } //Moq code: var mocker = new Mock

我有一个函数,我想要Moq。问题是它需要5个参数。该框架仅包含
Action
和Moq的generic
CallBack()
仅重载Action和四个generic版本。有没有一个优雅的解决办法

这就是我想做的:

public class Filter : IFilter  
{  
    public int Filter(int i1, int i2, int i3, int i4, int i5){return 0;}  
}

//Moq code:
var mocker = new Mock<IFilter>();  
mocker.Setup(x => x.Filter(  
    It.IsAny<int>(),  
    It.IsAny<int>(),  
    It.IsAny<int>(),  
    It.IsAny<int>(),  
    It.IsAny<int>(),  
    It.IsAny<int>())  
.Callback
(  
    (int i1, int i2, int i3, int i4, int i5) => i1 * 2  
);  
公共类筛选器:IFilter
{  
公共int筛选器(inti1、inti2、inti3、inti4、inti5){返回0;}
}
//最小起订量代码:
var mocker=new Mock();
mocker.Setup(x=>x.Filter(
It.IsAny(),
It.IsAny(),
It.IsAny(),
It.IsAny(),
It.IsAny(),
It.IsAny())
.回拨
(  
(inti1,inti2,inti3,inti4,inti5)=>i1*2
);  

Moq不允许这样做,因为没有需要5个以上参数的通用操作。我已经求助于制作自己的存根。显然,最好使用Moq进行所有验证,等等。

我知道这可能会破坏您的设计,但是有这么多参数,传递参数数组不是更好吗?

这实际上是q简单。只要定义你自己的
动作
,你就可以开始了

public delegate void Action<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5);
公共代表无效行动(T1、T2、T3、T4、T5);

这就是框架中定义的所有
操作
操作
,…,
操作
。仅此而已。简单!

如果不想修改源代码,请使用扩展方法扩展moq框架

//Extension Method

    public static class MoqExtensions
    {
        public static void Callback<T1, T2, T3, T4, T5>(this ICallback iCallBack, Action<T1, T2, T3, T4, T5> action)
        {
        }
    }

//Your class and interface

        public interface IMyClass
        {
            void Method(string arg1, string arg2, string arg3, string arg4, string arg5);
        }

        public class MyClass : IMyClass
        {
            public void Method(string arg1, string arg2, string arg3, string arg4, string arg5)
            {
                //Do something
            }
        }

//Your test

        [TestMethod]
        public void ExampleTest()
        {
            Mock<IMyClass> mockMyClass = new Mock<IMyClass>();
            mockMyClass.Setup(s => s.Method(It.IsAny<string>(),
                                            It.IsAny<string>(),
                                            It.IsAny<string>(),
                                            It.IsAny<string>(),
                                            It.IsAny<string>()))
                .Callback<string, string, string, string, string>((string arg1, string arg2, string arg3, string arg4, string arg5) 
                    => { /* Run your mock here */ });
        }
//扩展方法
公共静态类MoqExtensions
{
公共静态无效回调(此ICallback ICallback,操作)
{
}
}
//您的类和接口
公共接口IMyClass
{
void方法(字符串arg1、字符串arg2、字符串arg3、字符串arg4、字符串arg5);
}
公共类MyClass:IMyClass
{
公共void方法(字符串arg1、字符串arg2、字符串arg3、字符串arg4、字符串arg5)
{
//做点什么
}
}
//你的测试
[测试方法]
public void ExampleTest()
{
Mock mockMyClass=new Mock();
mockMyClass.Setup(s=>s.Method(It.IsAny()),
It.IsAny(),
It.IsAny(),
It.IsAny(),
It.IsAny())
.Callback((字符串arg1、字符串arg2、字符串arg3、字符串arg4、字符串arg5)
=>{/*在此处运行模拟*/});
}

这在Moq 4.0(4.0.10827)的最终版本中得到了支持,该版本于2011年4月12日发布。如果您使用.NET 4,您将能够模拟16个参数。

我知道这是一篇旧文章,但我认为此代码可能会帮助其他有此问题的人使用旧版本的Moq。下面是一个有5个和6个参数的示例,它可以扩展以支持任意数量的参数

我已经用版本3.1.0.0测试过了,但是它应该也可以用在其他版本上

秘密是使用反射访问基础类上的受保护方法“SetCallbackWithArguments”

希望这对某人有用

public delegate void Action<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
public delegate void Action<T1, T2, T3, T4, T5, T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);

public static class MoqExtensions
{
    public static ICallbackResult Callback<T1, T2, T3, T4, T5>(this ICallback call, Action<T1, T2, T3, T4, T5> callback)
    {
        call.SetCallbackWithArguments(callback);
        return (ICallbackResult)call;
    }

    public static ICallbackResult Callback<T1, T2, T3, T4, T5, T6>(this ICallback call, Action<T1, T2, T3, T4, T5, T6> callback)
    {
        call.SetCallbackWithArguments(callback);
        return (ICallbackResult)call;
    }

    public static void SetCallbackWithArguments(this ICallback call, Delegate callback)
    {
        MethodInfo methodInfo = call.GetType().GetMethod("SetCallbackWithArguments", BindingFlags.NonPublic | BindingFlags.Instance);
        methodInfo.Invoke(call, new object[] { callback });
    }
}
公共代理无效操作(T1 arg1、T2 arg2、T3 arg3、T4 arg4、T5 arg5);
公开代表无效行动(T1 arg1、T2 arg2、T3 arg3、T4 arg4、T5 arg5、T6 arg6);
公共静态类MoqExtensions
{
公共静态ICallbackResult回调(此ICallback调用、操作回调)
{
SetCallbackWithArguments(回调);
return(ICallbackResult)调用;
}
公共静态ICallbackResult回调(此ICallback调用、操作回调)
{
SetCallbackWithArguments(回调);
return(ICallbackResult)调用;
}
公共静态void SetCallbackWithArguments(此ICallback调用、委托回调)
{
MethodInfo MethodInfo=call.GetType().GetMethod(“SetCallbackWithArguments”,BindingFlags.NonPublic | BindingFlags.Instance);
调用(调用,新对象[]{callback});
}
}

可能不会对您有所帮助,但在.NET 4.0中,Action最多可以使用16个参数!即使您在.NET 4.0中,Moq在其最新的beta版中仍然最多只支持4个参数。要解决此问题,您必须下载源代码并自行下载。您可以使用扩展方法,您仍然需要修改Moq源代码以支持在回调中输入四个以上的参数。@“Robert Harvey”-是的,你是对的。我忽略了这一点。也许咖喱可以发挥作用?我看到的唯一解决方案是更改Moq重载以执行5个以上参数的操作。你说的“咖喱”是什么意思?+1,虽然参数对象可能更好,如果参数代表您在下一个响应中提到的不同概念,我需要更改Moq本身,因为它不允许此重载。无论如何,我需要泛型,以便访问调用参数。实际上,正如Mark指出的,更好的解决方案是传递一个objec不包含您需要的所有参数。当然,这将改变您模拟它的方式。然后呢?我仍然需要编写自己的方法,这并不比修改源代码简单。我更新了我的代码示例以提供一个简单的示例。您所做的只是扩展ICallback接口,它是moq框架的一部分。您是fa吗熟悉创建扩展方法吗?你的扩展方法实际上什么都不做,那么除了不让编译器抱怨之外,它如何工作呢?它工作得很好。不要因为你不能让它工作而放弃投票。你能给出一个你所做的示例吗。请参阅Paul Wardle的答案,它实际上完成了这是一个问题尝试。