IT
interface and a factory type method interface IT {} public IT CreateT(IA a, IB b, IC c, Type concreteType) { // , concreteType, . }
IT
have constructors with different signatures that accept some combination of objects of types IA
, IB
or IC
, so as the number of IT
implementations IT
, their creation code started to smell more and more, and finally, it was decided to throw it away simple code with Unity, something like this: private static IT CreateITInternal(IA a, Type targetType) { using (UnityContainer cont = new UnityContainer()) { cont.RegisterInstance<IA>(a, new ExternallyControlledLifetimeManager()); cont.RegisterType(typeof(IT), targetType, new ExternallyControlledLifetimeManager()); return cont.Resolve<IT>(); } }
IA
, so as not to clutter up the code. We need Unity here only to facilitate instantiation of objects and we don’t want to give it control over the lifetime of any objects, so ExternallyControlledLifetimeManager
used) private static IT CreateIT() { var a = new A(); Type concreteType = typeof(T); return CreateITInternal(a, concreteType); } static void Main(string[] args) { for (int i = 0; i < 1000; ++i) { CreateIT(); } }
public interface IA { }; public interface IT { }; public class A : IA { } public class T : IT { public T(IA a) { } }
Unhandled Exception: Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, type = "WeakRefTest.IT", name = "(none)". Exception occurred while: while resolving. Exception is: InvalidOperationException - The current type, WeakRefTest.IA, is an interface and cannot be constructed. Are you missing a type mapping? ----------------------------------------------- At the time of the exception, the container was: Resolving WeakRefTest.T,(none) (mapped from WeakRefTest.IT, (none)) Resolving parameter "a" of constructor WeakRefTest.T(WeakRefTest.IA a) Resolving WeakRefTest.IA,(none) ---> System.InvalidOperationException: The current type, WeakRefTest.IA, is an interface and cannot be constructed. Are you missing a type mapping?
at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructInterface(IBuilderContext context) at lambda_method(Closure , IBuilderContext ) at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context) at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) at lambda_method(Closure , IBuilderContext ) at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context) at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) --- End of inner exception stack trace --- at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides) at Microsoft.Practices.Unity.UnityContainerExtensions.Resolve[T](IUnityContainer container, ResolverOverride[] overrides) at WeakRefTest.Program.CreateITInternal(IA a, Type targetType) at WeakRefTest.Program.CreateIT() at WeakRefTest.Program.Main(String[] args)
ExternallyControlledLifetimeManager
, inside it keeps weak references to objects placed in the container, and it is possible if between placing an object of type IA
in a container and a request for constructing an object of type IT
it will be destroyed, then the design should fall just like that the exception. But on the other hand, an object of type IA
can only be removed if the weak link from our container is the only one, but in our case this is not the case! There are strong references to this object in CreateITInternal
and CreateIT
on the stack, which should extend its life at least until exiting CreateIT
. Or not? Checking: private static IT CreateITInternal(IA a, Type targetType) { using (UnityContainer cont = new UnityContainer()) { cont.RegisterInstance<IA>(a, new ExternallyControlledLifetimeManager()); cont.RegisterType(typeof(IT), targetType, new ExternallyControlledLifetimeManager()); GC.Collect(); return cont.Resolve<IT>(); } }
private static void TestWeakRef() { var sa = new A(); var wa = new WeakReference<A>(sa); GC.Collect(); A sa2; wa.TryGetTarget(out sa2); Console.WriteLine("{0}", sa2 == null ? "null" : "not null"); Console.ReadLine(); }
private static IT CreateITInternal(IA a, Type targetType) { using (UnityContainer cont = new UnityContainer()) { cont.RegisterInstance<IA>(a, new ExternallyControlledLifetimeManager()); cont.RegisterType(typeof(IT), targetType, new ExternallyControlledLifetimeManager()); IT ret = cont.Resolve<IT>(); GC.KeepAlive(a); return ret; } }
Source: https://habr.com/ru/post/268155/
All Articles