public InstanceProduct Produce() { var constructorArgumentProducers = _bindingExtender.BindingContainer.ConstructorArguments.ConvertAll( bft => new ConstructorArgumentProducer( _clusterBindings, _bindingExtender, bft ) ); var constructorArgumentProducts = constructorArgumentProducers .ConvertAll(p => p.Produce()) .FindAll(s => !ReferenceEquals(s, ConstructorArgumentProduct.Empty)) ; MethodProduct?predicateMethod = null; if (_bindingExtender.BindingContainer.IsConditional) { predicateMethod = new MethodProduct( $"CheckPredicate_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}", _typeInfoProvider.Bool(), (methodName, returnType) => $@" [MethodImpl(MethodImplOptions.AggressiveInlining)] private {returnType.ToDisplayString()} {methodName}(IResolutionTarget resolutionTarget) {{ Func<IResolutionTarget, bool> predicate = {_bindingExtender.BindingContainer.WhenArgumentClause} ; var result = predicate(resolutionTarget); return result; }} "); } var singletonInstanceName = $"_singletonInstance_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}"; var lockerName = $"_locker_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}"; var retrieveObjectMethod = new MethodProduct( $"GetInstance_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}", _bindingExtender.BindingContainer.BindToType, (methodName, returnType) => $@" private volatile {_bindingExtender.BindingContainer.BindToType.ToDisplayString()} {singletonInstanceName} = null; private readonly System.Object {lockerName} = new System.Object(); [MethodImpl(MethodImplOptions.AggressiveInlining)] private {returnType.ToDisplayString()} {methodName}( IResolutionTarget resolutionTarget ) {{ if({singletonInstanceName} is null) {{ lock({lockerName}) {{ if({singletonInstanceName} is null) {{ {singletonInstanceName} = new {_bindingExtender.BindingContainer.BindToType.ToDisplayString()}( {constructorArgumentProducts.Join(p => p.ResolveConstructorArgumentClause, ",")} ); }} }} }} return {singletonInstanceName}; }} "); var funcMethod = new MethodProduct( $"GetInstance_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}{DpdtArgumentWrapperTypeEnum.Func.GetPostfix()}", _typeInfoProvider.Func(_bindingExtender.BindingContainer.BindToType), (methodName, returnType) => $@" [MethodImpl(MethodImplOptions.AggressiveInlining)] private {returnType.ToDisplayString()} {methodName}( IResolutionTarget resolutionTarget ) {{ return () => {retrieveObjectMethod.GetMethodName(DpdtArgumentWrapperTypeEnum.None)}(resolutionTarget); }} "); var disposeMethodInvoke = new MethodProduct( $"DisposeInstance_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}", _typeInfoProvider.Void(), (methodName, returnType) => $@" private {returnType.ToDisplayString()} {methodName}( ) {{ if({singletonInstanceName} is {nameof(IDisposable)} d) {{ d.{nameof(IDisposable.Dispose)}(); }} }} "); var product = new InstanceProduct( _bindingExtender, predicateMethod, retrieveObjectMethod, funcMethod, disposeMethodInvoke ); return(product); }
public InstanceProduct Produce() { var constructorArgumentProducers = _bindingExtender.BindingContainer.ConstructorArguments.ConvertAll( bft => new ConstructorArgumentProducer( _clusterBindings, _bindingExtender, bft ) ); var constructorArgumentProducts = constructorArgumentProducers .ConvertAll(p => p.Produce()) .FindAll(s => !ReferenceEquals(s, ConstructorArgumentProduct.Empty)) ; MethodProduct?predicateMethod = null; if (_bindingExtender.BindingContainer.IsConditional) { predicateMethod = new MethodProduct( $"CheckPredicate_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}", _typeInfoProvider.Bool(), (methodName, returnType) => $@" [MethodImpl(MethodImplOptions.AggressiveInlining)] private {returnType.ToDisplayString()} {methodName}(IResolutionTarget resolutionTarget) {{ Func<IResolutionTarget, bool> predicate = {_bindingExtender.BindingContainer.WhenArgumentClause} ; var result = predicate(resolutionTarget); return result; }} "); } var scopeGuidName = $"_customScopeUniqueId_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}"; var retrieveObjectMethod = new MethodProduct( $"GetInstance_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}", _bindingExtender.BindingContainer.BindToType, (methodName, returnType) => $@" private readonly System.Guid {scopeGuidName} = new System.Guid(""{Guid.NewGuid()}""); [MethodImpl(MethodImplOptions.AggressiveInlining)] private {returnType.ToDisplayString()} {methodName}( IResolutionTarget resolutionTarget ) {{ if(resolutionTarget.ScopeObject is null) {{ RaiseNoCustomScopeObject<{_bindingExtender.BindingContainer.BindToType.ToDisplayString()}>(); }} var result = ({_bindingExtender.BindingContainer.BindToType.ToDisplayString()}) resolutionTarget.ScopeObject.GetOrAdd( {scopeGuidName}, () => new {_bindingExtender.BindingContainer.BindToType.ToDisplayString()}( {constructorArgumentProducts.Join(p => p.ResolveConstructorArgumentClause, ",")} ) ); return result; }} "); var funcMethod = new MethodProduct( $"GetInstance_{_bindingExtender.BindingContainer.GetStableSuffix()}_{ _bindingExtender.BindingContainer.BindToType.ToDisplayString().EscapeSpecialTypeSymbols()}{DpdtArgumentWrapperTypeEnum.Func.GetPostfix()}", _typeInfoProvider.Func(_bindingExtender.BindingContainer.BindToType), (methodName, returnType) => $@" [MethodImpl(MethodImplOptions.AggressiveInlining)] private {returnType.ToDisplayString()} {methodName}( IResolutionTarget resolutionTarget ) {{ return () => {retrieveObjectMethod.GetMethodName(DpdtArgumentWrapperTypeEnum.None)}(resolutionTarget); }} "); var product = new InstanceProduct( _bindingExtender, predicateMethod, retrieveObjectMethod, funcMethod, null ); return(product); }