C# 接口、Unity 和可选参数

C# Interface, Unity, and Optional Parameter

希望有人能阐明这一点。我有一个带有可选参数的接口。我们使用统一。如果我尝试更改方法实现中的可选参数,它会直接起作用,但 Unity 对象使用接口的默认值 - 而不是实现方法的默认值。

设置:

public interface ITestOptional   {
     string HappyMethod(string input, bool amHappy = false);
}

public class TestingOptional : ITestOptional   {
     public string HappyMethod(string input, bool amHappy = true) {
                if (amHappy) return input + " is Happy!";
                return input + " is Not Happy!";
     }
}

添加到 Unity:

container.RegisterType<ITestOptional, TestingOptional>();

并测试:

//direct call
var testDirect = new TestingOptional();
string happyDirect = testDirect.HappyMethod("Cow", true);  //expecting happy - get happy
string sadDirect = testDirect.HappyMethod("Cow", false);   //expecting not happy - get not happy
string defaultDirect = testDirect.HappyMethod("Cow"); //expecting happy (default) get happy

//unity
var testUnity = ServiceLocator.Current.GetInstance<ITestOptional>();

string happyUnity = testUnity.HappyMethod("Cow", true);  //expecting happy - get happy
string sadUnity = testUnity.HappyMethod("Cow", false);   //expecting not happy - get not happy
string defaultUnity = testUnity.HappyMethod("Cow"); //expecting happy (default) but get NOT happy.

知道为什么当实现使用 true 时 Unity 对象使用 false 作为可选参数吗?

您必须使用来自 IUnityContainer 实例的 Resolve<T> 方法。例如:

var testUnity = container.Resolve<ITestOptional>();

ServiceLocator.Current.GetInstance<ITestOptional>(); returns 编译类型 ITestOptional,因此对 testUnity.HappyMethod("Cow"); 的调用将由编译器转换为使用接口中指定的默认值。

类似地 new TestingOptional(); returns 编译时 TestingOptional 并且编译器将从 class.

中选择默认值

可能的解决方案(除了使用不同的默认值调整 expectations/not):您可以直接使用 Unity 解析该类型而不是解析接口(有时对测试有用):

  var directViaContainer = container.Resolve<TestingOptional>();

旁注:在 class 实现接口时重新定义默认值并不是什么好事——您会经常遇到这种令人困惑的代码。

在您的第一个示例中,您的 testDirect 是类型 TestingOptional 的一个实例,您可以使用它指定的默认参数值 [=14] 直接调用它的 HappyMethod 重载=].

在您的第二个示例中,您的 testUnity 是类型 ITestOptional 的实例,您调用它的 HappyMethod 指定不同的默认参数值 false

这与您创建这些实例的方式无关。如果您这样做,您会观察到相同的结果:

ITestOptional x = new TestingOptional();
x.HappyMethod("Cow");

这与Unity无关。这就是 C# 编译器的工作方式。可选参数由编译器在 编译时 填充。在第一个示例中,您在具体类型上调用了 HappyMethod 方法,并且该可选属性标记为 true,因此 C# 编译器将为您填写 true。然而,在第二个示例中,C# 编译器不知道实现的存在,所以它会查看接口的定义。猜猜是什么:该接口标有 false.