Reputation: 688
Hopefully someone can shed some light on this one. I have an interface with an optional parameter. We use Unity. If I try to change the optional parameter in the method implementation, it works directly, but the Unity object uses the interface's default - not the implemented method's default.
Setup:
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!";
}
}
Add to Unity:
container.RegisterType<ITestOptional, TestingOptional>();
And Test:
//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.
Any ideas why the Unity object uses false as the optional parameter when the implementation uses true?
Upvotes: 2
Views: 2569
Reputation: 172626
This has nothing to do with Unity. This is how C# compiler works. Optional arguments are filled in by the compiler at compile time. In the first example you call the HappyMethod
method on the concrete type and that optional attribute is marked with true
, so the C# compiler will fill in true for you. In the second example however, the C# compiler has no idea of the existence of the implementation, so it will look at the definition of the interface. And guess what: that interface is marked with false
.
Upvotes: 1
Reputation: 13224
In your first example, your testDirect
is an instance of type TestingOptional
, for which you invoke its HappyMethod
overload directly, using it's specified default parameter value of true
.
In your second example, your testUnity
is an instance of type ITestOptional
and you invoke its HappyMethod
that specifies a different default parameter value of false
.
This is unrelated to how you created these instances. You would have observed the same if you had done:
ITestOptional x = new TestingOptional();
x.HappyMethod("Cow");
Upvotes: 0
Reputation: 100527
ServiceLocator.Current.GetInstance<ITestOptional>();
returns compile type ITestOptional
, so call to testUnity.HappyMethod("Cow");
will be converted by compiler to use default value as specified in interface.
Similarly new TestingOptional();
returns compile time TestingOptional
and compiler will pick default from the class.
Possible solution (short of adjusting expectations/not using different defaults): you can resolve that type directly using Unity instead of resolving interfce (sometimes useful for tests):
var directViaContainer = container.Resolve<TestingOptional>();
Side note: re-defining default values in class implementing an interface is not a god practice - you'll get into this confusing code often.
Upvotes: 1
Reputation: 38598
You have to use the Resolve<T>
method, from an IUnityContainer
instance. For sample:
var testUnity = container.Resolve<ITestOptional>();
Upvotes: 0