| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| using System; |
| using System.Reflection; |
| using Org.Apache.REEF.Tang.Annotations; |
| using Org.Apache.REEF.Tang.Examples; |
| using Org.Apache.REEF.Tang.Exceptions; |
| using Org.Apache.REEF.Tang.Formats; |
| using Org.Apache.REEF.Tang.Implementations.InjectionPlan; |
| using Org.Apache.REEF.Tang.Implementations.Tang; |
| using Org.Apache.REEF.Tang.Interface; |
| using Org.Apache.REEF.Tang.Types; |
| using Org.Apache.REEF.Tang.Util; |
| using Xunit; |
| |
| namespace Org.Apache.REEF.Tang.Tests.Tang |
| { |
| public class TestTang |
| { |
| private static ITang tang; |
| |
| private static Assembly asm = null; |
| |
| public TestTang() |
| { |
| asm = Assembly.Load(FileNames.Examples); |
| MustBeSingleton.alreadyInstantiated = false; |
| tang = TangFactory.GetTang(); |
| } |
| |
| [Fact] |
| public void TestSingleton() |
| { |
| IInjector injector = tang.NewInjector(); |
| Assert.NotNull(injector.GetInstance(typeof(TwoSingletons))); |
| Assert.NotNull(injector.GetInstance(typeof(TwoSingletons))); |
| } |
| |
| [Fact] |
| public void TestNotSingleton() |
| { |
| TwoSingletons obj = null; |
| Assert.NotNull(tang.NewInjector().GetInstance(typeof(TwoSingletons))); |
| try |
| { |
| obj = (TwoSingletons)tang.NewInjector().GetInstance(typeof(TwoSingletons)); |
| } |
| catch (InjectionException) |
| { |
| } |
| Assert.Null(obj); |
| } |
| |
| [Fact] |
| public void TestRepeatedAmbiguousArgs() |
| { |
| INode node = null; |
| try |
| { |
| ICsConfigurationBuilder t = tang.NewConfigurationBuilder(); |
| node = |
| t.GetClassHierarchy() |
| .GetNode(ReflectionUtilities.GetAssemblyQualifiedName(typeof(RepeatedAmbiguousArgs))); |
| } |
| catch (ClassHierarchyException) |
| { |
| } |
| Assert.Null(node); |
| } |
| |
| [Fact] |
| public void TestRepeatedOKArgs() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| cb.BindNamedParameter<RepeatedNamedArgs.A, int>(GenericType<RepeatedNamedArgs.A>.Class, "1"); |
| cb.BindNamedParameter<RepeatedNamedArgs.B, int>(GenericType<RepeatedNamedArgs.B>.Class, "2"); |
| |
| IInjector injector = tang.NewInjector(cb.Build()); |
| injector.GetInstance(typeof(RepeatedNamedArgs)); |
| } |
| |
| // NamedParameter A has no default_value, so this should throw. |
| [Fact] |
| public void TestOneNamedFailArgs() |
| { |
| string msg = null; |
| try |
| { |
| tang.NewInjector().GetInstance<OneNamedSingletonArgs>(); |
| msg = |
| "Cannot inject OneNamedSingletonArgs: cOneNamedSingletonArgs missing argument OneNamedSingletonArgs+A"; |
| } |
| catch (Exception) |
| { |
| } |
| Assert.Null(msg); |
| } |
| |
| // NamedParameter A get's bound to a volatile, so this should succeed. |
| [Fact] |
| public void TestOneNamedSingletonOKArgs() |
| { |
| IInjector i = tang.NewInjector(); |
| i.BindVolatileParameter(GenericType<OneNamedSingletonArgs.A>.Class, i.GetInstance<MustBeSingleton>()); |
| OneNamedSingletonArgs o = i.GetInstance<OneNamedSingletonArgs>(); |
| Assert.NotNull(o); |
| } |
| |
| [Fact] |
| public void TestRepeatedNamedArgs() |
| { |
| IInjector i = tang.NewInjector(); |
| i.BindVolatileParameter(GenericType<RepeatedNamedSingletonArgs.A>.Class, |
| (MustBeSingleton)i.GetInstance(typeof(MustBeSingleton))); |
| i.BindVolatileParameter(GenericType<RepeatedNamedSingletonArgs.B>.Class, |
| (MustBeSingleton)i.GetInstance(typeof(MustBeSingleton))); |
| i.GetInstance(typeof(RepeatedNamedSingletonArgs)); |
| } |
| |
| [Fact] |
| public void testStraightforwardBuild() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| cb.BindImplementation(GenericType<Interf>.Class, GenericType<Impl>.Class); |
| tang.NewInjector(cb.Build()).GetInstance(typeof(Interf)); |
| } |
| |
| [Fact] |
| public void TestOneNamedStringArgCantRebind() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| OneNamedStringArg a = |
| (OneNamedStringArg)tang.NewInjector(cb.Build()).GetInstance(typeof(OneNamedStringArg)); |
| Assert.Equal("default", a.s); |
| cb.BindNamedParameter<OneNamedStringArg.A, string>(GenericType<OneNamedStringArg.A>.Class, "not default"); |
| IInjector i = tang.NewInjector(cb.Build()); |
| Assert.Equal("not default", ((OneNamedStringArg)i.GetInstance(typeof(OneNamedStringArg))).s); |
| string msg = null; |
| try |
| { |
| i.BindVolatileParameter(GenericType<OneNamedStringArg.A>.Class, "volatile"); |
| msg = |
| "Attempt to re-bind named parameter Org.Apache.REEF.Tang.OneNamedStringArg$A. Old value was [not default] new value is [volatile]"; |
| } |
| catch (Exception) |
| { |
| } |
| Assert.Null(msg); |
| } |
| |
| [Fact] |
| public void TestOneNamedStringArgBind() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| OneNamedStringArg a = tang.NewInjector(cb.Build()).GetInstance<OneNamedStringArg>(); |
| Assert.Equal("default", a.s); |
| cb.BindNamedParameter<OneNamedStringArg.A, string>(GenericType<OneNamedStringArg.A>.Class, "not default"); |
| IInjector i = tang.NewInjector(cb.Build()); |
| Assert.Equal("not default", i.GetInstance<OneNamedStringArg>().s); |
| } |
| |
| [Fact] |
| public void TestOneNamedStringArgVolatile() |
| { |
| OneNamedStringArg a = tang.NewInjector().GetInstance<OneNamedStringArg>(); |
| Assert.Equal("default", a.s); |
| IInjector i = tang.NewInjector(); |
| i.BindVolatileParameter(GenericType<OneNamedStringArg.A>.Class, "volatile"); |
| Assert.Equal("volatile", i.GetInstance<OneNamedStringArg>().s); |
| } |
| |
| [Fact] |
| public void TestTwoNamedStringArgsBind() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| TwoNamedStringArgs a = tang.NewInjector(cb.Build()).GetInstance<TwoNamedStringArgs>(); |
| Assert.Equal("defaultA", a.a); |
| Assert.Equal("defaultB", a.b); |
| cb.BindNamedParameter<TwoNamedStringArgs.A, string>(GenericType<TwoNamedStringArgs.A>.Class, "not defaultA"); |
| cb.BindNamedParameter<TwoNamedStringArgs.B, string>(GenericType<TwoNamedStringArgs.B>.Class, "not defaultB"); |
| IInjector i = tang.NewInjector(cb.Build()); |
| Assert.Equal("not defaultA", |
| i.GetInstance<TwoNamedStringArgs>().a); |
| Assert.Equal("not defaultB", |
| i.GetInstance<TwoNamedStringArgs>().b); |
| } |
| |
| [Fact] |
| public void TestTwoNamedStringArgsBindVolatile() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| TwoNamedStringArgs a = tang.NewInjector(cb.Build()).GetInstance<TwoNamedStringArgs>(); |
| Assert.Equal("defaultA", a.a); |
| Assert.Equal("defaultB", a.b); |
| IInjector i = tang.NewInjector(cb.Build()); |
| i.BindVolatileParameter(GenericType<TwoNamedStringArgs.A>.Class, "not defaultA"); |
| i.BindVolatileParameter(GenericType<TwoNamedStringArgs.B>.Class, "not defaultB"); |
| Assert.Equal("not defaultA", |
| i.GetInstance<TwoNamedStringArgs>().a); |
| Assert.Equal("not defaultB", |
| i.GetInstance<TwoNamedStringArgs>().b); |
| } |
| |
| [Fact] |
| public void TestTwoNamedStringArgsReBindVolatileFail() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| TwoNamedStringArgs a = tang.NewInjector(cb.Build()).GetInstance<TwoNamedStringArgs>(); |
| Assert.Equal("defaultA", a.a); |
| Assert.Equal("defaultB", a.b); |
| cb.BindNamedParameter<TwoNamedStringArgs.A, string>(GenericType<TwoNamedStringArgs.A>.Class, "not defaultA"); |
| cb.BindNamedParameter<TwoNamedStringArgs.B, string>(GenericType<TwoNamedStringArgs.B>.Class, "not defaultB"); |
| IInjector i = tang.NewInjector(cb.Build()); |
| string msg = null; |
| try |
| { |
| i.BindVolatileParameter(GenericType<TwoNamedStringArgs.A>.Class, "not defaultA"); |
| i.BindVolatileParameter(GenericType<TwoNamedStringArgs.B>.Class, "not defaultB"); |
| msg = |
| "Attempt to re-bind named parameter TwoNamedStringArgs+A. Old value was [not defaultA] new value is [not defaultA]"; |
| } |
| catch (Exception) |
| { |
| } |
| Assert.Null(msg); |
| } |
| |
| [Fact] |
| public void TestBextendsAinjectA() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| cb.BindImplementation(GenericType<BextendsAinjectA.A>.Class, GenericType<BextendsAinjectA.A>.Class); |
| BextendsAinjectA.A a = tang.NewInjector(cb.Build()).GetInstance<BextendsAinjectA.A>(); |
| Assert.NotNull(a); |
| } |
| |
| [Fact] |
| public void TestNamedImpl() |
| { |
| ICsConfigurationBuilder cb = TangFactory.GetTang().NewConfigurationBuilder(new string[] { FileNames.Examples }); |
| cb.BindNamedParameter<AImplName, Aimpl, INamedImplA>(GenericType<AImplName>.Class, GenericType<Aimpl>.Class); |
| cb.BindNamedParameter<BImplName, Bimpl, INamedImplA>(GenericType<BImplName>.Class, GenericType<Bimpl>.Class); |
| |
| IInjector i = TangFactory.GetTang().NewInjector(cb.Build()); |
| Aimpl a1 = (Aimpl)i.GetNamedInstance<AImplName, INamedImplA>(GenericType<AImplName>.Class); |
| Aimpl a2 = (Aimpl)i.GetNamedInstance<AImplName, INamedImplA>(GenericType<AImplName>.Class); |
| Bimpl b1 = (Bimpl)i.GetNamedInstance<BImplName, INamedImplA>(GenericType<BImplName>.Class); |
| Bimpl b2 = (Bimpl)i.GetNamedInstance<BImplName, INamedImplA>(GenericType<BImplName>.Class); |
| Assert.Same(a1, a2); |
| Assert.Same(b1, b2); |
| } |
| |
| [Fact] |
| public void testThreeConstructors() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| cb.BindNamedParameter<ThreeConstructors.TCInt, int>(GenericType<ThreeConstructors.TCInt>.Class, "1"); |
| cb.BindNamedParameter<ThreeConstructors.TCString, string>(GenericType<ThreeConstructors.TCString>.Class, "s"); |
| ThreeConstructors tc = tang.NewInjector(cb.Build()).GetInstance<ThreeConstructors>(); |
| Assert.Equal(1, tc.i); |
| Assert.Equal("s", tc.s); |
| |
| cb = tang.NewConfigurationBuilder(); |
| cb.BindNamedParameter<ThreeConstructors.TCInt, int>(GenericType<ThreeConstructors.TCInt>.Class, "1"); |
| tc = tang.NewInjector(cb.Build()).GetInstance<ThreeConstructors>(); |
| Assert.Equal(1, tc.i); |
| Assert.Equal("default", tc.s); |
| |
| cb = tang.NewConfigurationBuilder(); |
| cb.BindNamedParameter<ThreeConstructors.TCString, string>(GenericType<ThreeConstructors.TCString>.Class, "s"); |
| tc = tang.NewInjector(cb.Build()).GetInstance<ThreeConstructors>(); |
| Assert.Equal(-1, tc.i); |
| Assert.Equal("s", tc.s); |
| |
| cb = tang.NewConfigurationBuilder(); |
| cb.BindNamedParameter<ThreeConstructors.TCFloat, float>(GenericType<ThreeConstructors.TCFloat>.Class, "2"); |
| tc = tang.NewInjector(cb.Build()).GetInstance<ThreeConstructors>(); |
| Assert.Equal(-1, tc.i); |
| Assert.Equal("default", tc.s); |
| Assert.Equal(2.0f, tc.f, 9); |
| } |
| |
| [Fact] |
| public void TestThreeConstructorsAmbiguous() |
| { |
| string msg = null; |
| |
| try |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| cb.BindNamedParameter<ThreeConstructors.TCString, string>(GenericType<ThreeConstructors.TCString>.Class, "s"); |
| cb.BindNamedParameter<ThreeConstructors.TCFloat, float>(GenericType<ThreeConstructors.TCFloat>.Class, "-2"); |
| |
| // Ambiguous; there is a constructor that takes a string, and another that |
| // takes a float, but none that takes both. |
| tang.NewInjector(cb.Build()).GetInstance<ThreeConstructors>(); |
| msg = @"Cannot inject Org.Apache.REEF.Tang.Tests.Tang.ThreeConstructors, Org.Apache.REEF.Tang.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null " + |
| "Ambiguous subplan Org.Apache.REEF.Tang.Tests.Tang.ThreeConstructors, Org.Apache.REEF.Tang.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null " + |
| "new Org.Apache.REEF.Tang.Tests.Tang.ThreeConstructors(System.String Org.Apache.REEF.Tang.Tests.Tang.ThreeConstructors+TCString = s) " + |
| "new Org.Apache.REEF.Tang.Tests.Tang.ThreeConstructors(System.Single Org.Apache.REEF.Tang.Tests.Tang.ThreeConstructors+TCFloat = -2) "; |
| } |
| catch (InjectionException e) |
| { |
| System.Diagnostics.Debug.WriteLine(e); |
| } |
| Assert.Null(msg); |
| } |
| |
| [Fact] |
| public void TestTwoConstructorsAmbiguous() |
| { |
| string msg = null; |
| try |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| cb.BindNamedParameter<TwoConstructors.TCInt, int>(GenericType<TwoConstructors.TCInt>.Class, "1"); |
| cb.BindNamedParameter<ThreeConstructors.TCString, string>(GenericType<ThreeConstructors.TCString>.Class, "s"); |
| tang.NewInjector(cb.Build()).GetInstance<TwoConstructors>(); |
| msg = @"Cannot inject Org.Apache.REEF.Tang.Tests.Tang.TwoConstructors, Org.Apache.REEF.Tang.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null " + |
| "Ambiguous subplan Org.Apache.REEF.Tang.Tests.Tang.TwoConstructors, Org.Apache.REEF.Tang.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" + |
| "new Org.Apache.REEF.Tang.Tests.Tang.TwoConstructors(System.Int32 Org.Apache.REEF.Tang.Tests.Tang.TwoConstructors+TCInt = 1, System.String Org.Apache.REEF.Tang.Tests.Tang.TwoConstructors+TCString = s)" + |
| "new Org.Apache.REEF.Tang.Tests.Tang.TwoConstructors(System.String Org.Apache.REEF.Tang.Tests.Tang.TwoConstructors+TCString = s, System.Int32 Org.Apache.REEF.Tang.Tests.Tang.TwoConstructors+TCInt = 1)"; |
| } |
| catch (InjectionException e) |
| { |
| System.Diagnostics.Debug.WriteLine(e); |
| } |
| Assert.Null(msg); |
| } |
| |
| [Fact] |
| public void TestSingletonWithMultipleConstructors() |
| { |
| ICsConfigurationBuilder cb = TangFactory.GetTang().NewConfigurationBuilder(); |
| cb.BindImplementation(GenericType<SMC>.Class, GenericType<SingletonMultiConst>.Class); |
| cb.BindNamedParameter<SingletonMultiConst.A, string>(GenericType<SingletonMultiConst.A>.Class, "foo"); |
| IInjector i = TangFactory.GetTang().NewInjector(cb.Build()); |
| var o = i.GetInstance<SMC>(); |
| Assert.NotNull(o); |
| } |
| |
| [Fact] |
| public void TestSingletonWithMoreSpecificConstructors() |
| { |
| ICsConfigurationBuilder cb = TangFactory.GetTang().NewConfigurationBuilder(); |
| cb.BindImplementation(GenericType<SMC>.Class, GenericType<SingletonMultiConst>.Class); |
| cb.BindNamedParameter<SingletonMultiConst.A, string>(GenericType<SingletonMultiConst.A>.Class, "foo"); |
| cb.BindNamedParameter<SingletonMultiConst.B, string>(GenericType<SingletonMultiConst.B>.Class, "bar"); |
| IInjector i = TangFactory.GetTang().NewInjector(cb.Build()); |
| var o = i.GetInstance<SMC>(); |
| Assert.NotNull(o); |
| } |
| |
| [Fact] |
| public void TestInjectInjector() |
| { |
| IInjector i = TangFactory.GetTang().NewInjector(); |
| var ii = (InjectInjector)i.GetInstance(typeof(InjectInjector)); |
| //// Assert.True(ii.i is IInjector); |
| Assert.NotSame(i, ii.i); |
| } |
| |
| [Fact] |
| public void TestGenericEventHandlers() |
| { |
| ICsConfigurationBuilder cba = TangFactory.GetTang().NewConfigurationBuilder(); |
| cba.BindNamedParameter<ABCName.XName, ABCName.XXBB, ABCName.X<ABCName.BB>>(GenericType<ABCName.XName>.Class, GenericType<ABCName.XXBB>.Class); |
| TangFactory.GetTang().NewInjector(cba.Build()).GetNamedInstance(typeof(ABCName.XName)); |
| |
| ICsConfigurationBuilder cbb = TangFactory.GetTang().NewConfigurationBuilder(); |
| cbb.BindNamedParameter<ABCName.XName, ABCName.XBB, ABCName.X<ABCName.BB>>(GenericType<ABCName.XName>.Class, GenericType<ABCName.XBB>.Class); |
| TangFactory.GetTang().NewInjector(cbb.Build()).GetNamedInstance(typeof(ABCName.XName)); |
| } |
| |
| [Fact] |
| public void TestGenericEventHandlerDefaults() |
| { |
| ICsConfigurationBuilder cba = TangFactory.GetTang().NewConfigurationBuilder(); |
| var xbb = TangFactory.GetTang().NewInjector(cba.Build()).GetNamedInstance(typeof(ABCName.XNameDB)); |
| Assert.True(xbb is ABCName.XBB); |
| } |
| |
| [Fact] |
| public void TestGenericEventHandlerDefaultsGoodTreeIndirection() |
| { |
| ICsConfigurationBuilder cba = TangFactory.GetTang().NewConfigurationBuilder(); |
| var o = TangFactory.GetTang().NewInjector(cba.Build()).GetNamedInstance(typeof(ABCName.XNameDDAA)); |
| Assert.True(o is ABCName.XXBB); |
| } |
| |
| [Fact] |
| public void TestGenericUnrelatedGenericTypeParameters() |
| { |
| string msg = null; |
| try |
| { |
| ICsConfigurationBuilder cba = TangFactory.GetTang().NewConfigurationBuilder(); |
| TangFactory.GetTang().NewInjector(cba.Build()).GetNamedInstance(typeof(WaterBottleName)); |
| msg = |
| "class WaterBottleName defines a default class GasCan with a type that does not extend its target's type Water"; |
| } |
| catch (ClassHierarchyException e) |
| { |
| System.Diagnostics.Debug.WriteLine(e); |
| } |
| Assert.Null(msg); |
| } |
| |
| [Fact] |
| public void TestGenericInterfaceUnboundTypeParametersName() |
| { |
| ICsConfigurationBuilder cba = TangFactory.GetTang().NewConfigurationBuilder(); |
| var o = TangFactory.GetTang().NewInjector(cba.Build()).GetNamedInstance(typeof(FooEventHandler)); |
| Assert.True(o is MyEventHandler<Foo>); |
| } |
| |
| [Fact] |
| public void TestGenericInterfaceUnboundTypeParametersNameIface() |
| { |
| ICsConfigurationBuilder cba = TangFactory.GetTang().NewConfigurationBuilder(); |
| var o = TangFactory.GetTang().NewInjector(cba.Build()).GetNamedInstance(typeof(IfaceEventHandler)); |
| Assert.True(o is IEventHandler<SomeIface>); |
| } |
| |
| [Fact] |
| public void TestGenericInterfaceUnboundTypeParametersIface() |
| { |
| string msg = null; |
| try |
| { |
| ICsConfigurationBuilder cba = TangFactory.GetTang().NewConfigurationBuilder(); |
| TangFactory.GetTang().NewInjector(cba.Build()).IsInjectable(typeof(MyEventHandlerIface)); |
| msg = |
| "interface MyEventHandlerIface declares its default implementation to be non-subclass class MyEventHandler"; |
| } |
| catch (ClassHierarchyException e) |
| { |
| System.Diagnostics.Debug.WriteLine(e); |
| } |
| Assert.Null(msg); |
| } |
| |
| [Fact] |
| public void TestWantSomeHandlers() |
| { |
| var o = TangFactory.GetTang().NewInjector().GetInstance<WantSomeHandlers>(); |
| Assert.NotNull(o); |
| } |
| |
| [Fact] |
| public void TestWantSomeHandlersBadOrder() |
| { |
| IInjector i = TangFactory.GetTang().NewInjector(); |
| var o1 = i.GetInstance<IAHandler>(); |
| var o2 = i.GetInstance<IBHandler>(); |
| var o3 = i.GetInstance<WantSomeFutureHandlers>(); |
| Assert.True(o1 is AHandlerImpl); |
| Assert.True(o2 is BHandlerImpl); |
| Assert.NotNull(o3); |
| } |
| |
| [Fact] |
| public void TestWantSomeFutureHandlersAlreadyBoundVolatile() |
| { |
| IInjector i = TangFactory.GetTang().NewInjector(); |
| i.BindVolatileInstance(GenericType<IAHandler>.Class, new AHandlerImpl()); |
| i.BindVolatileInstance(GenericType<IBHandler>.Class, new BHandlerImpl()); |
| i.GetInstance<WantSomeFutureHandlers>(); |
| } |
| |
| [Fact] |
| public void TestWantSomeFutureHandlers() |
| { |
| TangFactory.GetTang().NewInjector().GetInstance<WantSomeFutureHandlers>(); |
| } |
| |
| [Fact] |
| public void TestWantSomeFutureHandlersName() |
| { |
| TangFactory.GetTang().NewInjector().GetInstance<WantSomeFutureHandlersName>(); |
| } |
| |
| [Fact] |
| public void TestReuseFailedInjector() |
| { |
| IInjector i = TangFactory.GetTang().NewInjector(); |
| try |
| { |
| i.GetInstance<Fail>(); |
| Assert.True(false, "Injecting Fail should not have worked!"); |
| } |
| catch (InjectionException) |
| { |
| i.GetInstance<Pass>(); |
| } |
| } |
| |
| [Fact] |
| public void TestMultipleLayersFromAbstractClass() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| cb.BindImplementation(GenericType<MultiLayer>.Class, GenericType<LowerLayer>.Class); |
| MultiLayer o = tang.NewInjector(cb.Build()).GetInstance<MultiLayer>(); |
| Assert.NotNull(o); |
| } |
| |
| [Fact] |
| public void TestMultipleLayersFromInterface() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(); |
| cb.BindImplementation(GenericType<IMultiLayer>.Class, GenericType<LowerLayerImpl>.Class); |
| IMultiLayer o = tang.NewInjector(cb.Build()).GetInstance<IMultiLayer>(); |
| Assert.NotNull(o); |
| } |
| |
| [Fact] |
| public void TestEmptyStringAsDefaultValue() |
| { |
| ICsConfigurationBuilder cb = tang.NewConfigurationBuilder(EmptyStringAsDefaultParamConf.ConfigurationModule.Build()); |
| var value = tang.NewInjector(cb.Build()).GetNamedInstance<EmptyStringAsDefaultParam, string>(); |
| Assert.NotNull(value.Equals(string.Empty)); |
| } |
| } |
| |
| internal class InjectInjector |
| { |
| public IInjector i; |
| |
| [Inject] |
| private InjectInjector(IInjector i) |
| { |
| this.i = i; |
| } |
| } |
| |
| internal class MustBeSingleton |
| { |
| public static bool alreadyInstantiated; |
| |
| [Inject] |
| public MustBeSingleton() |
| { |
| if (alreadyInstantiated) |
| { |
| throw new IllegalStateException("Can't instantiate me twice!"); |
| } |
| alreadyInstantiated = true; |
| } |
| } |
| |
| internal class SubSingleton |
| { |
| [Inject] |
| private SubSingleton(MustBeSingleton a) |
| { |
| // Does not call super |
| } |
| } |
| |
| internal class TwoSingletons |
| { |
| [Inject] |
| private TwoSingletons(SubSingleton a, MustBeSingleton b) |
| { |
| } |
| } |
| |
| internal class RepeatedAmbiguousArgs |
| { |
| [Inject] |
| private RepeatedAmbiguousArgs(int x, int y) |
| { |
| } |
| } |
| |
| public class RepeatedNamedArgs |
| { |
| [NamedParameter] |
| public class A : Name<int> |
| { |
| } |
| |
| [NamedParameter] |
| public class B : Name<int> |
| { |
| } |
| |
| [Inject] |
| public RepeatedNamedArgs([Parameter(typeof(A))] int x, [Parameter(Value = typeof(B))] int y) |
| { |
| } |
| } |
| |
| internal class RepeatedNamedSingletonArgs |
| { |
| [NamedParameter] |
| public class A : Name<MustBeSingleton> |
| { |
| } |
| |
| [NamedParameter] |
| public class B : Name<MustBeSingleton> |
| { |
| } |
| |
| [Inject] |
| public RepeatedNamedSingletonArgs([Parameter(typeof(A))] MustBeSingleton a, |
| [Parameter(typeof(B))] MustBeSingleton b) |
| { |
| } |
| } |
| |
| internal class OneNamedSingletonArgs |
| { |
| [NamedParameter] |
| public class A : Name<MustBeSingleton> |
| { |
| } |
| |
| [NamedParameter] |
| public class B : Name<MustBeSingleton> |
| { |
| } |
| |
| [Inject] |
| public OneNamedSingletonArgs([Parameter(typeof(A))] MustBeSingleton a) |
| { |
| } |
| } |
| |
| [NamedParameter(Documentation = "woo", ShortName = "woo", DefaultValue = "42")] |
| internal class Param : Name<int> |
| { |
| } |
| |
| internal interface Interf |
| { |
| } |
| |
| internal class Impl : Interf |
| { |
| [Inject] |
| private Impl([Parameter(Value = typeof(Param))] int p) |
| { |
| } |
| } |
| |
| internal class OneNamedStringArg |
| { |
| [NamedParameter(DefaultValue = "default")] |
| public class A : Name<string> |
| { |
| } |
| |
| public string s; |
| |
| [Inject] |
| private OneNamedStringArg([Parameter(typeof(A))] string s) |
| { |
| this.s = s; |
| } |
| } |
| |
| internal class TwoNamedStringArgs |
| { |
| [NamedParameter(DefaultValue = "defaultA")] |
| public class A : Name<string> |
| { |
| } |
| |
| [NamedParameter(DefaultValue = "defaultB")] |
| public class B : Name<string> |
| { |
| } |
| |
| public string a; |
| public string b; |
| |
| [Inject] |
| private TwoNamedStringArgs([Parameter(typeof(A))] string a, [Parameter(typeof(B))] string b) |
| { |
| this.a = a; |
| this.b = b; |
| } |
| } |
| |
| internal class BextendsAinjectA |
| { |
| public class A |
| { |
| [Inject] |
| public A() |
| { |
| } |
| } |
| |
| public class B : A |
| { |
| } |
| } |
| |
| public interface INamedImplA |
| { |
| } |
| |
| public interface INamedImplC |
| { |
| } |
| |
| [NamedParameter] |
| public class AImplName : Name<INamedImplA> |
| { |
| } |
| |
| [NamedParameter] |
| public class BImplName : Name<INamedImplA> |
| { |
| } |
| |
| [NamedParameter] |
| public class CImplName : Name<INamedImplC> |
| { |
| } |
| |
| public class Aimpl : INamedImplA |
| { |
| [Inject] |
| private Aimpl() |
| { |
| } |
| } |
| |
| public class Bimpl : INamedImplA |
| { |
| [Inject] |
| private Bimpl() |
| { |
| } |
| } |
| |
| public class Cimpl : INamedImplC |
| { |
| [Inject] |
| private Cimpl() |
| { |
| } |
| } |
| |
| internal class NamedImpl |
| { |
| [NamedParameter] |
| public class AImplName : Name<A> |
| { |
| } |
| |
| [NamedParameter] |
| public class BImplName : Name<A> |
| { |
| } |
| |
| [NamedParameter] |
| public class CImplName : Name<C> |
| { |
| } |
| |
| public interface A |
| { |
| } |
| |
| public interface C |
| { |
| } |
| |
| public class Aimpl : A |
| { |
| [Inject] |
| private Aimpl() |
| { |
| } |
| } |
| |
| public class Bimpl : A |
| { |
| [Inject] |
| private Bimpl() |
| { |
| } |
| } |
| |
| public class Cimpl : C |
| { |
| [Inject] |
| private Cimpl() |
| { |
| } |
| } |
| |
| public class ABtaker |
| { |
| [Inject] |
| private ABtaker([Parameter(typeof(AImplName))] INamedImplA a, [Parameter(typeof(BImplName))] INamedImplA b) |
| { |
| // Assert.True(a is Aimpl, "AImplName must be instance of Aimpl"); |
| // Assert.True(b is Bimpl, "BImplName must be instance of Bimpl"); |
| } |
| } |
| } |
| |
| [NamedParameter(DefaultValue = "")] |
| public class EmptyStringAsDefaultParam : Name<string> |
| { |
| } |
| |
| public class EmptyStringAsDefaultParamConf : ConfigurationModuleBuilder |
| { |
| public static readonly OptionalParameter<string> OptionalString = new OptionalParameter<string>(); |
| |
| public static ConfigurationModule ConfigurationModule = new EmptyStringAsDefaultParamConf() |
| .BindNamedParameter(GenericType<EmptyStringAsDefaultParam>.Class, OptionalString) |
| .Build(); |
| } |
| |
| [NamedParameter] |
| public class StringWithoutDefaultParam : Name<string> |
| { |
| } |
| |
| public class StringWithoutDefaultParamConf : ConfigurationModuleBuilder |
| { |
| public static readonly OptionalParameter<string> OptionalString = new OptionalParameter<string>(); |
| |
| public static ConfigurationModule ConfigurationModule = new StringWithoutDefaultParamConf() |
| .BindNamedParameter(GenericType<StringWithoutDefaultParam>.Class, OptionalString) |
| .Build(); |
| } |
| |
| class ThreeConstructors |
| { |
| public int i; |
| public string s; |
| public float f; |
| |
| [NamedParameter] |
| public class TCInt : Name<int> |
| { |
| } |
| |
| [NamedParameter] |
| public class TCString : Name<string> |
| { |
| } |
| |
| [NamedParameter] |
| public class TCFloat : Name<float> |
| { |
| } |
| |
| [Inject] |
| public ThreeConstructors([Parameter(typeof(TCInt))] int i, [Parameter(typeof(TCString))] string s) |
| { |
| this.i = i; |
| this.s = s; |
| this.f = -1.0f; |
| } |
| |
| [Inject] |
| public ThreeConstructors([Parameter(typeof(TCString))] string s) : this(-1, s) |
| { |
| } |
| |
| [Inject] |
| public ThreeConstructors([Parameter(typeof(TCInt))] int i) : this(i, "default") |
| { |
| } |
| |
| [Inject] |
| public ThreeConstructors([Parameter(typeof(TCFloat))] float f) |
| { |
| this.i = -1; |
| this.s = "default"; |
| this.f = f; |
| } |
| } |
| |
| class TwoConstructors |
| { |
| public int i; |
| public string s; |
| |
| [NamedParameter] |
| public class TCInt : Name<int> |
| { |
| } |
| |
| [NamedParameter] |
| public class TCString : Name<string> |
| { |
| } |
| |
| [Inject] |
| public TwoConstructors([Parameter(typeof(TCInt))] int i, [Parameter(typeof(TCString))] string s) |
| { |
| this.i = i; |
| this.s = s; |
| } |
| |
| [Inject] |
| public TwoConstructors([Parameter(typeof(TCString))] string s, [Parameter(typeof(TCInt))] int i) |
| { |
| this.i = i; |
| this.s = s; |
| } |
| } |
| |
| interface SMC |
| { |
| } |
| |
| class SingletonMultiConst : SMC |
| { |
| [NamedParameter] |
| public class A : Name<string> |
| { |
| } |
| |
| [NamedParameter] |
| public class B : Name<string> |
| { |
| } |
| |
| [Inject] |
| public SingletonMultiConst([Parameter(typeof(A))] string a) |
| { |
| } |
| |
| [Inject] |
| public SingletonMultiConst([Parameter(typeof(A))] string a, [Parameter(typeof(B))] string b) |
| { |
| } |
| } |
| |
| internal class ABCName |
| { |
| public interface X<T> |
| { |
| } |
| |
| [NamedParameter] |
| public class XName : Name<X<BB>> |
| { |
| } |
| |
| //// [NamedParameter(DefaultClass = typeof(XAA))] |
| //// public class XNameDA : Name<X<BB>> |
| //// { |
| //// } |
| |
| [NamedParameter(DefaultClass = typeof(XBB))] |
| public class XNameDB : Name<X<BB>> |
| { |
| } |
| |
| //// [NamedParameter(DefaultClass = typeof(XCC))] |
| //// public class XNameDC : Name<X<BB>> |
| //// { |
| //// } |
| |
| //// [NamedParameter(DefaultClass = typeof(XCC))] |
| //// public class XNameDAA : Name<XBB> |
| //// { |
| //// } |
| |
| [NamedParameter(DefaultClass = typeof(XXBB))] |
| public class XNameDDAA : Name<XBB> |
| { |
| } |
| |
| [DefaultImplementation(typeof(AA))] |
| public class AA |
| { |
| [Inject] |
| public AA() |
| { |
| } |
| } |
| |
| [DefaultImplementation(typeof(BB))] |
| public class BB : AA |
| { |
| [Inject] |
| public BB() |
| { |
| } |
| } |
| |
| [DefaultImplementation(typeof(CC))] |
| public class CC : BB |
| { |
| [Inject] |
| public CC() |
| { |
| } |
| } |
| |
| public class XAA : X<AA> |
| { |
| [Inject] |
| public XAA(AA aa) |
| { |
| } |
| } |
| |
| [DefaultImplementation(typeof(XBB))] |
| public class XBB : X<BB> |
| { |
| [Inject] |
| public XBB(BB aa) |
| { |
| } |
| } |
| |
| public class XXBB : XBB |
| { |
| [Inject] |
| public XXBB(BB aa) |
| : base(aa) |
| { |
| } |
| } |
| |
| public class XCC : X<CC> |
| { |
| [Inject] |
| public XCC(CC aa) |
| { |
| } |
| } |
| } |
| |
| interface Bottle<Y> |
| { |
| } |
| class WaterBottle : Bottle<Water> |
| { |
| } |
| class GasCan : Bottle<Gas> |
| { |
| } |
| class Water |
| { |
| } |
| class Gas |
| { |
| } |
| |
| [NamedParameter(DefaultClass = typeof(GasCan))] |
| class WaterBottleName : Name<Bottle<Water>> |
| { |
| } |
| |
| interface IEventHandler<T> |
| { |
| } |
| class MyEventHandler<T> : IEventHandler<T> |
| { |
| [Inject] |
| MyEventHandler() |
| { |
| } |
| } |
| |
| [DefaultImplementation(typeof(MyEventHandler<Foo>))] |
| interface MyEventHandlerIface : IEventHandler<Foo> |
| { |
| } |
| |
| [NamedParameter(DefaultClass = typeof(MyEventHandler<Foo>))] |
| class FooEventHandler : Name<IEventHandler<Foo>> |
| { |
| } |
| |
| internal class Foo : Name<string> |
| { |
| } |
| |
| interface SomeIface |
| { |
| } |
| |
| [NamedParameter(DefaultClass = typeof(MyEventHandler<SomeIface>))] |
| class IfaceEventHandler : Name<IEventHandler<SomeIface>> |
| { |
| } |
| |
| class AH |
| { |
| [Inject] |
| AH() |
| { |
| } |
| } |
| class BH |
| { |
| [Inject] |
| BH() |
| { |
| } |
| } |
| |
| [DefaultImplementation(typeof(AHandlerImpl))] |
| interface IAHandler : IEventHandler<AH> |
| { |
| } |
| |
| [DefaultImplementation(typeof(BHandlerImpl))] |
| interface IBHandler : IEventHandler<BH> |
| { |
| } |
| |
| class AHandlerImpl : IAHandler |
| { |
| [Inject] |
| public AHandlerImpl() |
| { |
| } |
| } |
| class BHandlerImpl : IBHandler |
| { |
| [Inject] |
| public BHandlerImpl() |
| { |
| } |
| } |
| |
| class WantSomeHandlers |
| { |
| [Inject] |
| WantSomeHandlers(IAHandler a, IBHandler b) |
| { |
| } |
| } |
| class WantSomeFutureHandlers |
| { |
| [Inject] |
| WantSomeFutureHandlers(IInjectionFuture<IAHandler> a, IInjectionFuture<IBHandler> b) |
| { |
| } |
| } |
| |
| [NamedParameter(DefaultClass = typeof(AHandlerImpl))] |
| class AHandlerName : Name<IEventHandler<AH>> |
| { |
| } |
| |
| [NamedParameter(DefaultClass = typeof(BHandlerImpl))] |
| class BHandlerName : Name<IEventHandler<BH>> |
| { |
| } |
| |
| class WantSomeFutureHandlersName |
| { |
| [Inject] |
| WantSomeFutureHandlersName( |
| [Parameter(typeof(AHandlerName))] IInjectionFuture<IEventHandler<AH>> a, |
| [Parameter(typeof(BHandlerName))] IInjectionFuture<IEventHandler<BH>> b) |
| { |
| } |
| } |
| |
| class Pass |
| { |
| [Inject] |
| public Pass() |
| { |
| } |
| } |
| |
| class Fail |
| { |
| [Inject] |
| public Fail() |
| { |
| throw new NotSupportedException(); |
| } |
| } |
| |
| abstract class MultiLayer |
| { |
| } |
| |
| class MiddleLayer : MultiLayer |
| { |
| [Inject] |
| public MiddleLayer() |
| { |
| } |
| } |
| |
| class LowerLayer : MiddleLayer |
| { |
| [Inject] |
| public LowerLayer() |
| { |
| } |
| } |
| |
| interface IMultiLayer |
| { |
| } |
| |
| class MiddleLayerImpl : IMultiLayer |
| { |
| [Inject] |
| public MiddleLayerImpl() |
| { |
| } |
| } |
| |
| class LowerLayerImpl : MiddleLayerImpl |
| { |
| [Inject] |
| public LowerLayerImpl() |
| { |
| } |
| } |
| } |