Exemplo n.º 1
0
        public static string[] FixAnnotation(Type type, params string[] annotations)
        {
            Injectable constructor = type.GetConstructorFunction();

            string[] parameters = null;

            if (annotations != null && annotations.Length > 0)
            {
                // annotations are specified as argument
                parameters = annotations;
            }
            else
            {
                var attrs = type.GetCustomAttributes(typeof(InjectAttribute), true);
                if (attrs.Length != 0)
                {
                    // annotations are specified with the [Inject] decorator
                    parameters = (attrs[0] as InjectAttribute).Injectables;
                }
                // TODO check Inject attribute in constructors too?
                else
                {
                    // annotations are read from constructor parameter names
                    // fix "$" in parameter names
                    parameters = PatchDollarName(Angular.Injector().Annotate(constructor));
                }
            }

            // annotations are stored in type.$inject
            constructor.Inject = parameters;

            return(parameters);
        }
        private static Function CreateAnimationFunction(Type type)
        {
            string body    = "";
            string thisref = "this";

            body += "var $animob = {};\r\n";

            // gets and annotate constructor parameter; annotations are stored in type.$inject
            var parameters = Angular.Injector().Annotate(type.GetConstructorFunction());

            // takes method into $scope, binding "$scope" to "this"
            foreach (string funcname in type.GetInstanceMethodNames())
            {
                body += String.Format("{2}.{1} = {0}.prototype.{1}.bind({2});\r\n", type.FullName, funcname, thisref);

                if (funcname == "Start" || funcname == "Setup" || funcname == "Cancel")
                {
                    body += String.Format("$animob.{0} = {2}.{1};\r\n", funcname.ToLower(), funcname, thisref);
                }
            }

            // put call at the end so that methods are defined first
            body += String.Format("{0}.apply({1},arguments);\r\n", type.FullName, thisref);
            body += String.Format("return $animob;\r\n");
            return(TypeExtensionMethods.CreateNewFunction(parameters, body));
        }
        //[InlineCode("{module}.service({$System.Script}.getTypeName({T}),{T})")]
        public static void Service <T>(this Module module)
        {
            Type type       = typeof(T);
            var  parameters = Angular.Injector().Annotate(type.GetConstructorFunction());

            type.ToFunction().CreateFunctionCall(parameters); // only used to fix the "_" to "$" in type.$inject
            string servicename = typeof(T).Name;

            Service(module, servicename, type);
        }
Exemplo n.º 4
0
        // Providers are injectable classes containing a callable method that returns a new instance of the service.
        // Both the class and the factory methods have different injections because they are called at distinct times.
        // The class (constructor function) is called at config phase, while the method is called when the service
        // needs to be instantiated. For convention, the class must me named with suffix "Provider" and the method
        // must be of equal name without the suffix (e.g. "UserProvider" and "User").

        public static void Provider <T>(this Module module, params string[] annotations)
        {
            Type type       = typeof(T);
            var  parameters = FixAnnotation(type, annotations);
            var  plist      = CommaSeparatedList(parameters);

            string providerName = type.FullName;

            if (!providerName.EndsWith("Provider"))
            {
                throw new Exception("provider names must end with the suffix 'Provider'");
            }
            string serviceName = providerName.Substring(0, providerName.Length - 8);

            string[] annotations_factory_method = null;

            Function factory_method = type.GetMethodAsFunction(serviceName);

            if (Angular.IsUndefined(factory_method))
            {
                throw new Exception("provider class must contain a factory method named '" + serviceName + "'");
            }

            // looks for factory method, and its Inject attribute
            foreach (var method in type.GetMethods(BindingFlags.Instance | BindingFlags.Public))
            {
                if (method.Name == serviceName)
                {
                    object[] attrs = method.GetCustomAttributes(typeof(InjectAttribute));
                    if (attrs != null && attrs.Length > 0)
                    {
                        InjectAttribute attr = attrs[0] as InjectAttribute;
                        annotations_factory_method = attr.Injectables;
                        break;
                    }
                }
            }

            if (annotations_factory_method == null)
            {
                // if [Inject] was not specified, look for inline annotations
                annotations_factory_method = PatchDollarName(Angular.Injector().Annotate(factory_method));
            }

            // Inject annotations for the factory method
            Injectable.From(factory_method).Inject = annotations_factory_method;

            // creates a wrapped function around the provider class. The provider class in instantiated and the $get is filled.
            string   body = "var $ob = new " + type.FullName + "(" + plist + "); $ob.$get = $ob." + serviceName + "; return $ob;";
            Function F    = new Function(parameters, body);

            Injectable.From(F).Inject = parameters;

            Provider(module, serviceName, F);
        }
        public static void Animation <T>(this Module module, string name = null)
        {
            Type type = typeof(T);

            // TODO when there will be IsSubClassOf
            //if(!type.IsSubclassOf(DirectiveDefinition)) throw new Exception(String.Format("{0} is not sub class of {1}",type.Name,typeof(DirectiveDefinition).Name);

            Function fun        = CreateAnimationFunction(type);
            var      parameters = Angular.Injector().Annotate(fun);
            var      fcall      = fun.CreateFunctionCall(parameters);

            Animation(module, name == null ? type.Name : name, fcall);
        }
        public static void Directive <T>(this Module module)
        {
            Type type = typeof(T);

            // TODO when there will be IsSubClassOf
            //if(!type.IsSubclassOf(DirectiveDefinition)) throw new Exception(String.Format("{0} is not sub class of {1}",type.Name,typeof(DirectiveDefinition).Name);

            DirectiveDefinition dirob = (DirectiveDefinition)Activator.CreateInstance(type);

            Function fun        = CreateDirectiveFunction(dirob);
            var      parameters = Angular.Injector().Annotate(fun);
            var      fcall      = fun.CreateFunctionCall(parameters);

            Directive(module, dirob.Name, fcall);
        }
        public static Function BuildControllerFunction(this Type type, ThisMode this_mode, string return_function = null, bool return_function_call = false)
        {
            string body    = "";
            string thisref = "";

            if (this_mode == ThisMode.NewObject)
            {
                thisref = "$self";
            }
            else if (this_mode == ThisMode.ScopeStrict)
            {
                thisref = "_scope";
            }
            else if (this_mode == ThisMode.Scope)
            {
                thisref = "_scope";
            }
            else if (this_mode == ThisMode.This)
            {
                thisref = "this";
            }

            if (this_mode == ThisMode.NewObject)
            {
                body += "var $self = new Object();";
            }

            // gets and annotate constructor parameter; annotations are stored in type.$inject
            var parameters = Angular.Injector().Annotate(type.GetConstructorFunction());

            if (this_mode == ThisMode.ScopeStrict)
            {
                // verifies that "scope" is the first parameter in constructor
                if (parameters.Count < 1 || parameters[0] != "_scope")
                {
                    throw new Exception(String.Format("Controller {0} must specify '_scope' as first parameter in its constructor", type.Name));
                }
            }

            // takes method into $scope, binding "$scope" to "this"
            foreach (string funcname in type.GetInstanceMethodNames())
            {
                body += String.Format("{2}.{1} = {0}.prototype.{1}.bind({2});\r\n", type.FullName, funcname, thisref);
            }

            // put call at the end so that methods are defined first
            body += String.Format("{0}.apply({1},arguments);\r\n", type.FullName, thisref);

            if (return_function != null)
            {
                if (return_function_call)
                {
                    body += String.Format("return {1}.{0}();\r\n", return_function, thisref);
                }
                else
                {
                    body += String.Format("return {1}.{0}  ;\r\n", return_function, thisref);
                }

                if (!type.GetInstanceMethodNames().Contains(return_function))
                {
                    throw new Exception("function '" + return_function + "' not defined in controller '" + type.Name + "'");
                }
            }

            return(TypeExtensionMethods.CreateNewFunction(parameters, body));
        }
        private static Function CreateDirectiveFunction(DirectiveDefinition def)
        {
            object defob = def.CreateDefinitionObject();

            List <string> parameters = new List <string>();
            List <string> fnames     = new List <string>();

            Type type = def.DirectiveController;

            object SharedController = ((dynamic)defob).controller;

            if (type != null)
            {
                parameters = Angular.Injector().Annotate(type.GetConstructorFunction());
                fnames     = type.GetInstanceMethodNames();
            }

            string body = "";

            body += "var $obdef = " + Json.Stringify(defob) + ";\r\n";

            if (type != null)
            {
                if (fnames.Contains("Link"))
                {
                    body += "var $outer_arguments = arguments;\r\n";
                    body += "$obdef.link = function(_scope) { \r\n";

                    // save isolated scope bindings that would be overwritten by constructor initialization
                    foreach (ScopeBindings sb in def.ScopeAttributes)
                    {
                        body += String.Format("var $$saved_{0} = _scope.{0};\r\n", sb.AttributeName);
                    }

                    foreach (string funcname in fnames)
                    {
                        body += String.Format("   _scope.{1} = {0}.prototype.{1}.bind(_scope);\r\n", type.FullName, funcname);
                    }

                    body += String.Format("   {0}.apply(_scope,$outer_arguments);\r\n", type.FullName);

                    // retrieves back saved isolated scope bindings
                    foreach (ScopeBindings sb in def.ScopeAttributes)
                    {
                        body += String.Format("_scope.{0} = $$saved_{0};\r\n", sb.AttributeName);
                    }

                    body += "   _scope.Link.apply(_scope,arguments);\r\n";
                    body += "}\r\n";
                }
                else
                {
                    throw new Exception("Link() method not defined in directive controller");
                }
            }

            if (SharedController != null)
            {
                body += "$obdef.controller = " + SharedController.ToString() + ";";
            }

            body += "return $obdef;\r\n";

            return(TypeExtensionMethods.CreateNewFunction(parameters, body));
        }