示例#1
0
        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);
            }
        }
示例#2
0
        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();
        }
示例#3
0
        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());
        }
示例#4
0
        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));
        }
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        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);
            }
        }
示例#8
0
        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");
            }
        }
示例#9
0
        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");
            }
        }
示例#10
0
 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("}");
 }
示例#11
0
        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("}");
        }
示例#12
0
        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");
            }
        }