private static void RenderProviderGetter(StringWriter rw, InjectionSpecificationInjection injection, EmittedKernelSpec spec) { if (injection.Singleton) { rw.WriteLine("static {0}() {{", injection.ConcreteClassName); rw.WriteLine("{0} = new Lazy<{1}>(() => {{", spec.PrivateFieldName, spec.PrivateFieldType); } else { rw.WriteLine("{0} static {1} Get() {{", _renderAccessModifier, spec.ReturnType); } rw.WriteLine("var x = new {0}().Create();", injection.Provider); rw.WriteLine("return x;"); if (injection.Singleton) { rw.WriteLine("});"); rw.WriteLine("}"); rw.WriteLine("{0} static {1} Get() {{ return {2}.Value; }}", _renderAccessModifier, spec.ReturnType, spec.PrivateFieldName); rw.WriteLine("{0} static Lazy<{1}> GetLazy() {{ return {2}; }}", _renderAccessModifier, spec.ReturnType, spec.PrivateFieldName); } else { rw.WriteLine("}"); rw.WriteLine("{0} static Lazy<{1}> GetLazy() {{ return new Lazy<{1}>(Get); }}", _renderAccessModifier, spec.ReturnType); } }
private static IList<string> CalculateNamespacesForInjection(InjectionSpecificationInjection injection) { var usedTypes = new List<string>(); if (!string.IsNullOrEmpty(injection.Concrete)) { usedTypes.Add(injection.Concrete); } if (!string.IsNullOrEmpty(injection.Provider)) { usedTypes.Add(injection.Provider); } if (injection.Interface != null) { usedTypes.AddRange( from @interface in injection.Interface where !string.IsNullOrEmpty(@interface.Value) select @interface.Value); } return (from type in usedTypes select FileScan(type, false) into file where file != null select file.Namespace).ToList(); }
private static IList <string> CalculateNamespacesForInjection(InjectionSpecificationInjection injection) { var usedTypes = new List <string>(); if (!string.IsNullOrEmpty(injection.Concrete)) { usedTypes.Add(injection.Concrete); } if (!string.IsNullOrEmpty(injection.Provider)) { usedTypes.Add(injection.Provider); } if (injection.Interface != null) { usedTypes.AddRange( from @interface in injection.Interface where !string.IsNullOrEmpty(@interface.Value) select @interface.Value); } return((from type in usedTypes select FileScan(type, false) into file where file != null select file.Namespace).ToList()); }
private static string GetConcreteYieldingFunction(string interfaceRequired) { var isLazy = interfaceRequired.StartsWith("Lazy<"); if (isLazy) { interfaceRequired = interfaceRequired.Substring(5, interfaceRequired.Length - 6); } // Detect if self-bound var selfBound = _injectionList.Where(injection => injection.Concrete == interfaceRequired).ToArray(); if (selfBound.Length >= 2) { throw new Exception("Ambiguous reference"); } InjectionSpecificationInjection foundInjection = null; if (selfBound.Length == 1) { foundInjection = selfBound.First(); //.ConcreteYieldingFunction; } foreach (var injection in _injectionList) { if (injection.Interface == null) { continue; } if (injection.Interface.Any(x => x.Value == interfaceRequired)) { foundInjection = injection; break; } } if (foundInjection == null) { string message = string.Format( "The interface {0} is required by injection, but not defined in the InjectionSpecification", interfaceRequired); throw new InvalidOperationException(message); } if (foundInjection.Interface != null && foundInjection.Interface.Length > 1) { // return the specific interface rather than the underlying concrete return(foundInjection.InterfaceYieldingFunction(interfaceRequired, isLazy)); } return(foundInjection.ConcreteYieldingFunction(isLazy)); }
private static void AddRenderedKernel(EmittedKernelSpec spec, InjectionSpecificationInjection injection) { spec.Namespaces = CalculateNamespacesForInjection(injection); spec.Namespaces = spec.Namespaces.Distinct().ToList(); if (RenderedKernels.ContainsKey(spec.KernelClassName)) { throw new InvalidOperationException("Not unique?"); } RenderedKernels.Add(spec.KernelClassName, spec); }
private static void AddRenderedKernel(EmittedKernelSpec spec, InjectionSpecificationInjection injection) { spec.Namespaces = CalculateNamespacesForInjection(injection); spec.Namespaces = spec.Namespaces.Distinct().ToList(); if (RenderedKernels.ContainsKey(spec.KernelClassName)) { throw new InvalidOperationException("Not unique?"); } RenderedKernels.Add(spec.KernelClassName, spec); }
private static void RenderConcreteBuilderGetter(StringWriter rw, InjectionSpecificationInjection injection, EmittedKernelSpec spec) { if (!string.IsNullOrEmpty(injection.Provider)) { throw new ParseException("Injection concrete '{0}' alse has provider '{1}' defined", injection.Concrete, injection.Provider); } string concreteToBuild = injection.Concrete; CSharpFile fileDefinition = injection.NoScan ? new CSharpFile(concreteToBuild) : FileScan(concreteToBuild, true); if (injection.Singleton) { rw.WriteLine("static {0}() {{", injection.ConcreteClassName); rw.WriteLine("{0} = new Lazy<{1}>(() => {{", spec.PrivateFieldName, spec.PrivateFieldType); } else { rw.WriteLine("{0} static {1} Get() {{", _renderAccessModifier, spec.ReturnType); } // There is no StackTrace on Metro :-( if (!_inputTokens.Contains("NETFX_CORE")) { if (!spec.IsDebug) { rw.WriteLine("#if DEBUG"); } rw.WriteLine("var stack = new StackTrace().GetFrames();"); rw.WriteLine("var methodName = stack.First().GetMethod().DeclaringType.Name;"); rw.WriteLine("if (stack.Count(y => y.GetMethod().DeclaringType.Name == methodName) > 2) { throw new Exception(\"Infinite loop detected\"); }"); if (!spec.IsDebug) { rw.WriteLine("#endif"); } } if (_benchmarking) { if (!spec.IsDebug) { rw.WriteLine("#if DEBUG"); } rw.WriteLine("Debug.WriteLine(\"Thread(\" + System.Threading.Thread.CurrentThread.ManagedThreadId + \") : Kernel TypeConstruct: {0}\");", injection.ConcreteClassName); rw.WriteLine("var stopWatch = System.Diagnostics.Stopwatch.StartNew();"); if (!spec.IsDebug) { rw.WriteLine("#endif"); } } rw.WriteLine("var x = new {0}(", concreteToBuild); if (injection.ConstructorArgument != null && injection.ConstructorArgument.Length > 0) { InjectionSpecificationInjectionConstructorArgument[] cArgs = injection.ConstructorArgument; for (int i = 0; i < cArgs.Length; i++) { if (i != 0) { rw.Write(','); } rw.WriteLine(injection.ConstructorArgument[i].Value); } } else { IList <string> cArgs = fileDefinition.ConstructorArgs ?? new List <string>(); for (int i = 0; i < cArgs.Count; i++) { if (i != 0) { rw.Write(','); } string interfaceRequired = cArgs[i]; string concreteFunction = GetConcreteYieldingFunction(interfaceRequired); rw.WriteLine(concreteFunction); } } rw.WriteLine(");"); if (_benchmarking) { if (!spec.IsDebug) { rw.WriteLine("#if DEBUG"); } rw.WriteLine("stopWatch.Stop();"); rw.WriteLine("Debug.WriteLine(\"Thread(\" + System.Threading.Thread.CurrentThread.ManagedThreadId + \") : Kernel TypeConstruct: {0}, MillisecondsElapsed: \" + stopWatch.ElapsedMilliseconds);", injection.ConcreteClassName); if (!spec.IsDebug) { rw.WriteLine("#endif"); } } if (!injection.NoScan) { if (_benchmarking) { if (!spec.IsDebug) { rw.WriteLine("#if DEBUG"); } rw.WriteLine("stopWatch = System.Diagnostics.Stopwatch.StartNew();"); if (!spec.IsDebug) { rw.WriteLine("#endif"); } } var hasProperties = RenderPropertyInjections(rw, fileDefinition); if (_benchmarking) { if (!spec.IsDebug) { rw.WriteLine("#if DEBUG"); } rw.WriteLine("stopWatch.Stop();"); if (hasProperties) { rw.WriteLine("Debug.WriteLine(\"Thread(\" + System.Threading.Thread.CurrentThread.ManagedThreadId + \") : Kernel TypePropertiesSet: {0}, MillisecondsElapsed: \" + stopWatch.ElapsedMilliseconds);", injection.ConcreteClassName); } if (!spec.IsDebug) { rw.WriteLine("#endif"); } } } rw.WriteLine("return x;"); if (injection.Singleton) { rw.WriteLine("});"); rw.WriteLine("}"); rw.WriteLine("{0} static {1} Get() {{ return {2}.Value; }}", _renderAccessModifier, spec.ReturnType, spec.PrivateFieldName); rw.WriteLine("{0} static Lazy<{1}> GetLazy() {{ return {2}; }}", _renderAccessModifier, spec.ReturnType, spec.PrivateFieldName); } else { rw.WriteLine("}"); rw.WriteLine("{0} static Lazy<{1}> GetLazy() {{ return new Lazy<{1}>(Get); }}", _renderAccessModifier, spec.ReturnType, spec.PrivateFieldName); } }
private static void Render(StringWriter rw, InjectionSpecificationInjection injection) { if (injection == null) { throw new ArgumentNullException("injection"); } bool debugEmit = injection.DebugOnly; if (debugEmit) { rw.WriteLine("#if DEBUG"); } string outerKernelClassName = injection.ConcreteClassName; var spec = new EmittedKernelSpec { KernelClassName = outerKernelClassName, IsDebug = injection.DebugOnly, Singleton = injection.Singleton }; rw.WriteLine("[CoverageExclude]"); rw.WriteLine("{0} static class {1} {{", _renderAccessModifier, outerKernelClassName); if (!string.IsNullOrEmpty(injection.Provider)) { if (injection.Interface.Length == 1) { spec.PrivateFieldType = injection.Interface.First().Value; } else { if (string.IsNullOrEmpty(injection.Concrete)) { throw new Exception("Providers with no concrete and interfaces.Count != 1 not supported"); } spec.PrivateFieldType = injection.Concrete; } if (injection.Singleton) { spec.PrivateFieldName = RenderPrivateField(rw, spec, injection.Singleton); } spec.ReturnType = injection.Interface != null && injection.Interface.Length == 1 ? injection.Interface.First().Value : injection.Concrete; RenderProviderGetter(rw, injection, spec); if (injection.Singleton) { RenderClearAndRebind(rw, spec); } } else if (!string.IsNullOrEmpty(injection.Concrete)) { spec.PrivateFieldType = injection.Interface != null && injection.Interface.Length == 1 ? injection.Interface.First().Value : injection.Concrete; spec.ReturnType = spec.PrivateFieldType; if (injection.Singleton) { spec.PrivateFieldName = RenderPrivateField(rw, spec, injection.Singleton); } RenderConcreteBuilderGetter(rw, injection, spec); if (injection.Singleton) { RenderClearAndRebind(rw, spec); } } else { throw new ParseException("Injection defined with no Concrete or Provider?"); } rw.WriteLine('}'); AddRenderedKernel(spec, injection); // Render additional interfaces... if (injection.Interface != null) { foreach (InjectionSpecificationInjectionInterface @interface in injection.Interface) { string interfaceName = @interface.Value; if (!interfaceName.StartsWith("I")) { throw new ParseException( string.Format( "All interfaces need to start with 'I'. Check the InjectionSpecification is formated correctly without line breaks or similare in the node. Current interface name being read: '{0}'.", interfaceName)); } string interfaceNameNoI = interfaceName.Substring(1, interfaceName.Length - 1).RemoveDodgyTokens(); EmittedKernelSpec existingSpec = RenderedKernels.Where(x => x.Value.ReturnType == interfaceName).Select(x => x.Value). SingleOrDefault(); if (!injection.ShouldHaveConcreteCoreRender && existingSpec != null) { // We've already built this above... continue; } // Render Kernel Reference which points to the concrete... var spec2 = new EmittedKernelSpec { KernelClassName = string.Format("Kernel_{0}", interfaceNameNoI), PrivateFieldType = interfaceName, IsDebug = false, Singleton = injection.Singleton }; rw.WriteLine("[CoverageExclude]"); rw.WriteLine("{0} static class {1} {{", _renderAccessModifier, spec2.KernelClassName); spec2.ReturnType = spec2.PrivateFieldType; if (injection.Singleton) { spec2.PrivateFieldName = RenderPrivateField(rw, spec2, injection.Singleton); rw.WriteLine( "static {0}() {{ {1} = new Lazy<{2}>({3}.Get); }}", spec2.KernelClassName, spec2.PrivateFieldName, spec2.ReturnType, injection.ConcreteClassName); rw.WriteLine( "{0} static {1} Get() {{ return {2}.Value; }}", _renderAccessModifier, spec2.ReturnType, spec2.PrivateFieldName); rw.WriteLine( "{0} static Lazy<{1}> GetLazy() {{ return {2}; }}", _renderAccessModifier, spec2.ReturnType, spec2.PrivateFieldName); RenderClearAndRebind(rw, spec2); } else { rw.WriteLine( "{0} static {1} Get() {{ return {3}.Get(); }}", _renderAccessModifier, spec2.ReturnType, spec2.PrivateFieldName, injection.ConcreteClassName); rw.WriteLine( "{0} static Lazy<{1}> GetLazy() {{ return new Lazy<{1}>({2}.Get); }}", _renderAccessModifier, spec2.ReturnType, injection.ConcreteClassName); } rw.WriteLine('}'); AddRenderedKernel(spec2, injection); } } if (debugEmit) { rw.WriteLine("#endif"); } }
private static void RenderStaticConstructorDebugLog(InjectionSpecificationInjection injection, bool debugIfDefsAlreadyEmitted, StringWriter rw) { if (!debugIfDefsAlreadyEmitted) { rw.WriteLine("#if DEBUG"); } rw.WriteLine("static {0}() {{ Debug.WriteLine(\"Kernel TypeLoad: {0}\"); }}", injection.ConcreteClassName); if (!debugIfDefsAlreadyEmitted) { rw.WriteLine("#endif"); } }
private static void RenderProviderGetter(StringWriter rw, InjectionSpecificationInjection injection, EmittedKernelSpec spec) { rw.WriteLine("{0} static {1} Get() {{", _renderAccessModifier, spec.ReturnType); if (injection.Singleton) { rw.WriteLine("if({0} != null) return {0};", spec.PrivateFieldName); } rw.WriteLine("{0} = new {1}().Create();", spec.PrivateFieldName, injection.Provider); rw.WriteLine("return {0};", spec.PrivateFieldName); rw.WriteLine("}"); }
private static void RenderConcreteBuilderGetter(StringWriter rw, InjectionSpecificationInjection injection, EmittedKernelSpec spec) { if (!string.IsNullOrEmpty(injection.Provider)) { throw new ParseException("Injection concrete '{0}' alse has provider '{1}' defined", injection.Concrete, injection.Provider); } string concreteToBuild = injection.Concrete; CSharpFile fileDefinition = injection.NoScan ? new CSharpFile(concreteToBuild) : FileScan(concreteToBuild, true); rw.WriteLine("{0} static {1} Get() {{", _renderAccessModifier, spec.ReturnType); if (injection.Singleton) { rw.WriteLine("if({0} != null) return {0};", spec.PrivateFieldName); } // There is no StackTrace on Metro :-( if (!_inputTokens.Contains("NETFX_CORE")) { if (!spec.IsDebug) { rw.WriteLine("#if DEBUG"); } rw.WriteLine("var stack = new StackTrace().GetFrames();"); rw.WriteLine("var methodName = stack.First().GetMethod().DeclaringType.Name;"); rw.WriteLine( "if (stack.Count(y => y.GetMethod().DeclaringType.Name == methodName) > 1) { throw new Exception(\"Infinite loop detected\"); }"); if (!spec.IsDebug) { rw.WriteLine("#endif"); } } rw.WriteLine("var x = new {0}(", concreteToBuild); if (injection.ConstructorArgument != null && injection.ConstructorArgument.Length > 0) { InjectionSpecificationInjectionConstructorArgument[] cArgs = injection.ConstructorArgument; for (int i = 0; i < cArgs.Length; i++) { if (i != 0) { rw.Write(','); } rw.WriteLine(injection.ConstructorArgument[i].Value); } } else { IList<string> cArgs = fileDefinition.ConstructorArgs ?? new List<string>(); for (int i = 0; i < cArgs.Count; i++) { if (i != 0) { rw.Write(','); } string interfaceRequired = cArgs[i]; string concreteFunction = GetConcreteYieldingFunction(interfaceRequired); rw.WriteLine(concreteFunction); } } rw.WriteLine(");"); rw.WriteLine("{0} = x;", spec.PrivateFieldName); if (!injection.NoScan) { RenderPropertyInjections(rw, fileDefinition); } rw.WriteLine("return {0};", spec.PrivateFieldName); rw.WriteLine("}"); }
private static void Render(StringWriter rw, InjectionSpecificationInjection injection) { if (injection == null) { throw new ArgumentNullException("injection"); } bool debugEmit = injection.DebugOnly; if (debugEmit) { rw.WriteLine("#if DEBUG"); } string outerKernelClassName = injection.ConcreteClassName; var spec = new EmittedKernelSpec { KernelClassName = outerKernelClassName, IsDebug = injection.DebugOnly }; rw.WriteLine("[CoverageExclude]"); rw.WriteLine("{0} static class {1} {{", _renderAccessModifier, outerKernelClassName); RenderStaticConstructorDebugLog(injection, debugEmit, rw); if (!string.IsNullOrEmpty(injection.Provider)) { if (string.IsNullOrEmpty(injection.Concrete)) { if (injection.Interface.Count() != 1) { throw new Exception("Providers with no concrete and interfaces.Count != 1 not supported"); } spec.PrivateFieldType = injection.Interface.First().Value; spec.PrivateFieldName = RenderPrivateField(rw, spec); } else { spec.PrivateFieldType = injection.Concrete; spec.PrivateFieldName = RenderPrivateField(rw, spec); } spec.ReturnType = injection.Interface != null && injection.Interface.Length == 1 ? injection.Interface.First().Value : injection.Concrete; RenderProviderGetter(rw, injection, spec); RenderClearAndRebind(rw, spec); } else if (!string.IsNullOrEmpty(injection.Concrete)) { spec.PrivateFieldType = injection.Interface != null && injection.Interface.Length == 1 ? injection.Interface.First().Value : injection.Concrete; spec.ReturnType = spec.PrivateFieldType; spec.PrivateFieldName = RenderPrivateField(rw, spec); RenderConcreteBuilderGetter(rw, injection, spec); RenderClearAndRebind(rw, spec); } else { throw new ParseException("Injection defined with no Concrete or Provider?"); } rw.WriteLine('}'); AddRenderedKernel(spec, injection); // Render additional interfaces... if (injection.Interface != null) { foreach (InjectionSpecificationInjectionInterface @interface in injection.Interface) { string interfaceName = @interface.Value; if (!interfaceName.StartsWith("I")) { throw new ParseException( string.Format( "All interfaces need to start with 'I'. Check the InjectionSpecification is formated correctly without line breaks or similare in the node. Current interface name being read: '{0}'.", interfaceName)); } string interfaceNameNoI = interfaceName.Substring(1, interfaceName.Length - 1).RemoveDodgyTokens(); EmittedKernelSpec existingSpec = RenderedKernels.Where(x => x.Value.ReturnType == interfaceName).Select(x => x.Value). SingleOrDefault(); if (!injection.ShouldHaveConcreteCoreRender && existingSpec != null) { // We've already built this above... continue; } // Render Kernel Reference which points to the concrete... var spec2 = new EmittedKernelSpec { KernelClassName = string.Format("Kernel_{0}", interfaceNameNoI), PrivateFieldType = interfaceName, IsDebug = false }; rw.WriteLine("[CoverageExclude]"); rw.WriteLine("{0} static class {1} {{", _renderAccessModifier, spec2.KernelClassName); spec2.PrivateFieldName = RenderPrivateField(rw, spec2); spec2.ReturnType = spec2.PrivateFieldType; rw.WriteLine( "{0} static {1} Get() {{ if({2} != null) {{ return {2}; }} var x = {3}.Get(); {2} = x; return x; }}", _renderAccessModifier, spec2.ReturnType, spec2.PrivateFieldName, injection.ConcreteClassName); RenderClearAndRebind(rw, spec2); rw.WriteLine('}'); AddRenderedKernel(spec2, injection); } } if (debugEmit) { rw.WriteLine("#endif"); } }