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); }
// 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)); }