private void InitService() { ServiceDescriptor[] items = new ServiceDescriptor[mSettingHandler.Services.Count]; mSettingHandler.Services.CopyTo(items, 0); foreach (var item in items) { mHttpControllerServices.Insert(0, item); } foreach (Assembly item in mSettingHandler.Assemblies) { Type[] types = item.GetTypes(); foreach (Type type in types) { ControllerAttribute ca = type.GetCustomAttribute <ControllerAttribute>(false); if (ca != null) { if (ca.SingleInstance) { mHttpControllerServices.AddSingleton(type); } else { mHttpControllerServices.AddScoped(type); } } } } mHttpControllerServices.AddSingleton(mHttpServer); mHttpControllerServiceProvider = mHttpControllerServices.BuildServiceProvider(); if (mSettingHandler.Assemblies != null) { mHttpServer.Register(mSettingHandler.Assemblies); } }
private static IControllerBinding[] GetControllerBindings(Type type) { IControllerBinding[] bindings; if (!_typeControllers.TryGetValue(type, out bindings)) { lock(_typeControllers) { object[] attributes = type.GetCustomAttributes(typeof(IControllerBinding), false); if (attributes.Length == 0) { if (typeof(IController).IsAssignableFrom(type)) { IControllerBinding b = new ControllerAttribute(); b.Initialize(type); bindings = new IControllerBinding[] { b }; } else return null; } else { bindings = new IControllerBinding[attributes.Length]; for (int i = 0; i < attributes.Length; i++) { IControllerBinding b = (IControllerBinding)attributes[i]; b.Initialize(type); bindings[i] = b; } } _typeControllers.Add(type, bindings); } } return bindings; }
private void OnRegister(ControllerAttribute attribute, Type type, object controller) { foreach (Type itype in attribute.Types) { if (!itype.IsInterface) { continue; } if (type.GetInterface(itype.Name) == null) { continue; } string url = "/" + (attribute.Name ?? itype.Name) + "/"; foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance)) { try { if (string.Compare("Equals", method.Name, true) == 0 || string.Compare("GetHashCode", method.Name, true) == 0 || string.Compare("GetType", method.Name, true) == 0 || string.Compare("ToString", method.Name, true) == 0 || method.Name.IndexOf("set_") >= 0 || method.Name.IndexOf("get_") >= 0) { continue; } ActionAttribute aa = method.GetCustomAttribute <ActionAttribute>(false); var actionUrl = url + (aa == null ? method.Name : aa.Name); if (mActionHadlers.TryGetValue(actionUrl, out ActionHandler handler)) { Server.Log(EventArgs.LogType.Warring, $"{itype.Name}->{type.Name}.{method.Name} action already exists, can add ActionAttribute on the method"); } else { handler = new ActionHandler(type, method, controller); handler.SingleInstance = attribute.SingleInstance; handler.Interface = itype; mActionHadlers[actionUrl] = handler; Server.Log(EventArgs.LogType.Info, $"Register {itype.Name}->{type.Name}@{method.Name} to {actionUrl}"); } } catch (Exception e_) { Server.Log(EventArgs.LogType.Error, $"Register {itype.Name}->{type.Name}@{method.Name} action error {e_.Message}@{e_.StackTrace}"); } } } }
public bool AppliesToEndpoints(IReadOnlyList <Endpoint> endpoints) { // Don't apply this filter to any endpoint group that is a controller route // i.e. only dynamic routes. foreach (Endpoint endpoint in endpoints) { ControllerAttribute controller = endpoint.Metadata?.GetMetadata <ControllerAttribute>(); if (controller != null) { return(false); } } // then ensure this is only applied if all endpoints are IDynamicEndpointMetadata return(endpoints.All(x => x.Metadata?.GetMetadata <IDynamicEndpointMetadata>() != null)); }
public void LoadRouting(Assembly assembly) { if (assembly is null) { return; } List <Endpoint> endpoints = new List <Endpoint>(); Type[] classes = assembly.GetTypes(); for (int classIndex = 0; classIndex < classes.Length; classIndex++) { Type currentClass = classes[classIndex]; ControllerAttribute controllerAttribute = currentClass.GetCustomAttribute <ControllerAttribute>(); if (controllerAttribute != null) { MethodInfo[] methods = currentClass.GetMethods(); for (int methodIndex = 0; methodIndex < methods.Length; methodIndex++) { MethodInfo currentMethod = methods[methodIndex]; IEnumerable <Attribute> Attributes = currentMethod.GetCustomAttributes(); foreach (Attribute currentAttribute in Attributes) { if (currentAttribute is BaseEndpointAttribute endpointAttribute) { string controllerPath = controllerAttribute.Path.Replace("[controller]", currentClass.Name.RemoveAtEnd("Context")); string methodPath = endpointAttribute.Path.Replace("[method]", currentMethod.Name); string path = controllerPath + methodPath; endpoints.Add(new Endpoint() { ClassExecuted = currentClass, ParameterInfo = currentMethod.GetParameters().ToArray(), MethodExecuted = currentMethod.CreateReflectedDelegate(), Method = endpointAttribute.Method, Path = path, Priority = CalculatePriority(path), ReturnIsGenericType = currentMethod.ReturnType.IsGenericType }); } } } } }
public static void AddControllerActions(object controller, HttpServer server) { Attribute attribute = Attribute.GetCustomAttribute(controller.GetType(), typeof(ControllerAttribute)); if (attribute == null) { throw new InvalidOperationException("Class " + controller.GetType() + " does not have a ControllerAttribute."); } ControllerAttribute controllerAttribute = attribute as ControllerAttribute; // ReSharper disable once PossibleNullReferenceException if (controllerAttribute.ControllerRoute == null) { controllerAttribute.ControllerRoute = "/" + controller.GetType().Name.Replace("Controller", ""); } MethodInfo[] methods = controller.GetType() .GetMethods() .Where(y => y.GetCustomAttributes(true).OfType <RouteAttribute>().Any()) .ToArray(); foreach (var method in methods) { RouteAttribute routeAttribute = method.GetCustomAttribute <RouteAttribute>(); if (routeAttribute.Path == null) { routeAttribute.Path = method.Name; } if (method.ReturnType == typeof(string) && method.GetParameters().Length == 1 && method.GetParameters()[0].ParameterType == typeof(HttpListenerRequest)) { server.GetRegistrator(routeAttribute.HttpMethod)[controllerAttribute.ControllerRoute + "/" + routeAttribute.Path] = (Func <HttpListenerRequest, string>) Delegate.CreateDelegate(typeof(Func <HttpListenerRequest, string>), controller, method); } } }
/// <summary> /// Gets a byte representation of the data requested in this HttpListenerContext request /// </summary> /// <param name="sender">Sender of the call</param> /// <param name="context">Context of the HTTP request</param> /// <param name="controllers">Relevant controllers to be searched for methods</param> /// <returns>a byte representation of the data requested in this HttpListenerContext request</returns> public static byte[] handleResponse(SaneServer sender, HttpListenerContext context, List <Type> controllers) { List <HttpArgument> arguments = new List <HttpArgument>(); MethodInfo[][] info = controllers.Select((g) => (g.GetMethods().Where((x) => (x.GetCustomAttribute <ControllerAttribute>() != null || x.GetCustomAttribute <DataBoundViewAttribute>() != null)).ToArray())).ToArray(); List <MethodInfo> methods = new List <MethodInfo>(); for (int i = 0; i < info.Length; i++) { for (int j = 0; j < info[i].Length; j++) { methods.Add(info[i][j]); } } foreach (String key in context.Request.QueryString.AllKeys) { arguments.Add(new HttpArgument(key, context.Request.QueryString.GetValues(key).First())); } byte[] returned = new byte[] { }; foreach (MethodInfo method in methods) { ControllerAttribute attribute = method.GetCustomAttribute <ControllerAttribute>(); if (attribute == null) { continue; } String trimmed = context.Request.RawUrl.Substring(0, context.Request.RawUrl.LastIndexOf("/") + 1); if ((attribute.path.Substring(0).Equals(trimmed)) && (attribute.verb.Equals(context.Request.HttpMethod))) { try { ParameterInfo[] parameters = method.GetParameters(); Dictionary <ParameterInfo, String> match = new Dictionary <ParameterInfo, String>(); foreach (ParameterInfo parameter in parameters) { foreach (HttpArgument argument in arguments) { if (argument.key.Equals(parameter.Name)) { match[parameter] = argument.value; } } } object[] finalized = new object[parameters.Length]; finalized[0] = context; if (context.Request.HasEntityBody) { finalized[1] = new StreamReader(context.Request.InputStream).ReadToEnd(); } else { finalized[1] = String.Empty; } for (int i = 2; i < parameters.Length; i++) { finalized[i] = (match.ContainsKey(parameters[i])) ? match[parameters[i]] : null; } context.Response.ContentType = attribute.contentType; if (method.ReturnType.Equals((new byte[] { }).GetType())) { return((byte[])method.Invoke(null, finalized)); } else { return(Encoding.UTF8.GetBytes(method.Invoke(null, finalized) + "")); } } catch (Exception e) { context.Response.ContentType = attribute.contentType; if (sender.GetErrorHandler() != null) { context.Response.StatusCode = 400; SaneErrorEventArgs args = new SaneErrorEventArgs(ResponseErrorReason.INTERNAL_API_THROW, e, false, ""); sender.GetErrorHandler()(null, args); if (args.Propogate) { return(Encoding.UTF8.GetBytes(args.Response)); } else { return(new byte[] { }); } } else { context.Response.StatusCode = 400; return(Encoding.UTF8.GetBytes("An error occured processing your request, and no error handler is currently set!")); } } } else if ((attribute.path.Substring(0).Equals(trimmed))) { if (sender.GetErrorHandler() != null) { context.Response.StatusCode = 400; SaneErrorEventArgs args = new SaneErrorEventArgs(ResponseErrorReason.INCORRECT_API_TYPE, new Exception("Incorrect API request type! Got " + context.Request.HttpMethod + ", expected " + attribute.verb + "!"), false, ""); sender.GetErrorHandler()(null, args); if (args.Propogate) { return(Encoding.UTF8.GetBytes(args.Response)); } else { return(new byte[] { }); } } else { context.Response.StatusCode = 400; return(Encoding.UTF8.GetBytes("An error occured processing your request, and no error handler is currently set!")); } } } Assembly assembly = Assembly.GetEntryAssembly(); XmlDocument structure = sender.GetViewStructure(); XmlNodeList resources = structure.SelectNodes("view/resource"); String request = context.Request.RawUrl.Substring(1).Replace("/", "."); XmlNode homePage = null; XmlNode notFound = null; foreach (XmlNode node in resources) { if (request.Equals(node.Attributes["path"].Value.Replace("/", "."))) { context.Response.ContentType = node.Attributes["content-type"].Value; byte[] clientData = Utility.fetchForClient(assembly, node.Attributes["location"].Value); foreach (MethodInfo method in methods) { DataBoundViewAttribute attribute = method.GetCustomAttribute <DataBoundViewAttribute>(); if (attribute == null) { continue; } if ((attribute.path.Equals(context.Request.RawUrl))) { Object binding = method.Invoke(null, new object[] { context }); DataBoundView boundView = new DataBoundView(clientData, binding); return(Encoding.UTF8.GetBytes(boundView.html)); } } return(clientData); } if (node.Attributes["situational"] != null) { String value = node.Attributes["situational"].Value; if (value.Equals("homepage")) { homePage = node; } else if (value.Equals("404")) { notFound = node; } } } if (context.Request.RawUrl.Trim().Length <= 1) { context.Response.ContentType = "text/html"; byte[] clientData = new byte[] { }; if (homePage != null) { clientData = Utility.fetchForClient(assembly, homePage.Attributes["location"].Value.Replace("/", ".")); foreach (MethodInfo method in methods) { DataBoundViewAttribute attribute = method.GetCustomAttribute <DataBoundViewAttribute>(); if (attribute == null) { continue; } if ((attribute.path.Substring(1).Equals(homePage.Attributes["path"].Value))) { Object binding = method.Invoke(null, new object[] { context }); DataBoundView boundView = new DataBoundView(clientData, binding); return(Encoding.UTF8.GetBytes(boundView.html)); } } } return(clientData); } context.Response.StatusCode = 404; context.Response.ContentType = "text/html"; byte[] ret = new byte[] { }; if (notFound != null) { ret = Utility.fetchForClient(assembly, notFound.Attributes["location"].Value.Replace("/", ".")); foreach (MethodInfo method in methods) { DataBoundViewAttribute attribute = method.GetCustomAttribute <DataBoundViewAttribute>(); if (attribute == null) { continue; } if ((attribute.path.Substring(1).Equals(notFound.Attributes["path"].Value))) { Object binding = method.Invoke(null, new object[] { context }); DataBoundView boundView = new DataBoundView(ret, binding); return(Encoding.UTF8.GetBytes(boundView.html)); } } } return(ret); }
// <summary> /// Search through indicated namespaces and scan for all annotated classes. /// Automatically create bindings /// </summary> /// <param name="usingNamespaces">Array of namespaces. Compared using StartsWith. </param> protected virtual void ScanForAnnotatedClasses(string[] usingNamespaces) { #if DEBUG watch.Start(); #endif if (assembly != null) { IEnumerable <Type> types = assembly.GetExportedTypes(); List <Type> typesInNamespaces = new List <Type>(); int namespacesLength = usingNamespaces.Length; for (int ns = 0; ns < namespacesLength; ns++) { typesInNamespaces.AddRange(types.Where(t => !string.IsNullOrEmpty(t.Namespace) && t.Namespace.StartsWith(usingNamespaces[ns]))); } foreach (Type type in typesInNamespaces) { object[] implements = type.GetCustomAttributes(typeof(ModleAttribute), false); if (implements.Any()) { ModleAttribute mat = (ModleAttribute)implements[0]; if (mat.type == DataSource.FromNetwork) { IIModelNetwork.Add(type); } else if (mat.type == DataSource.FromLocal) { IIModelConfig.Add(type); } else if (mat.type == DataSource.FromBoth) { IIModelBoth.Add(type); } } implements = type.GetCustomAttributes(typeof(ControllerAttribute), false); if (implements.Any()) { ControllerAttribute mat = (ControllerAttribute)implements[0]; IController.Add(mat.ctrlType.ToString(), type); /// /// 查找Controller继承自IGameState接口 /// if (type.GetInterfaces().Contains(typeof(IGameState))) { IControllerGamePlay.Add(mat.ctrlType); } /// /// 查找Controller继承自IDeviceState接口 /// if (type.GetInterfaces().Contains(typeof(IDeviceState))) { IControllerDevice.Add(mat.ctrlType); } } } } #if DEBUG ConsoleEx.DebugLog("Scan For Annotated Classes costs " + watch.ElapsedMilliseconds + " miliseconds to be done!"); watch.Reset(); #endif }
/// <summary> /// Reads a controller from a stream. If the controller is not implemented, the raw data is returned as byte array. /// </summary> /// <param name="stream"></param> /// <param name="controllerName">The name of the controller or null if the controller must be auto-detected (not optimal, some controllers cannot be detected).</param> /// <returns></returns> public object Read(Stream stream, string controllerName) { long currentPos = stream.Position; int availableData = (int)(stream.Length - stream.Position); var reader = new BinaryReader(stream, FileEncoding.Default); // In case of a normal controller (10/-1) subtype the next Int32 contains the size of the following structure. In case of animation controllers (sub type 0/1/2/4/5/6), see below. int controllerSize = reader.ReadInt32(); // The size read from the stream matches the available data (incl. the 4 bytes of the Int32 already read), then we have a normal controller. Otherwise, we have to do some more logic to determine correct type of controller. // PROBLEM: In the odd unlucky case the size of a controller may match exactly, and it is then assumed to be a behavior controller. bool isBaseController = controllerSize + 4 != availableData; var profile = ControllerProfile.Unknown; // Base or animation controller? (byte stream) if (isBaseController) { // First 4 bytes means something else. ushort animationControllerSubType = unchecked ((ushort)(controllerSize & 0xFFFF)); ushort unknown = unchecked ((ushort)((controllerSize & 0xFFFF0000) >> 16)); if (string.IsNullOrEmpty(controllerName)) { // If no name provided, check if sub type matches that of an animation controller. if (Enum.IsDefined(typeof(AnimationType), animationControllerSubType)) { controllerName = ((AnimationType)animationControllerSubType).ToString(); } } // Only continue reading if we have a controller name. if (!string.IsNullOrEmpty(controllerName)) { profile = _controllerAssembly.GetControllerProfilesByName(controllerName).FirstOrDefault(); if (profile != ControllerProfile.Unknown && _controllerAssembly.TryGetControllerType(controllerName, profile, out Type controllerType)) { // Check if the controller is indeed a base/animation controller. If it isn't, the size descriptor may have contained an invalid size for controller data. We just attempt normal deserialization then. if (!controllerType.IsBehaviorController()) { ControllerAttribute controllerAttribute = controllerType.GetCustomAttribute <ControllerAttribute>() ?? new ControllerAttribute(); // Check that the detected controller matches subtype. if (controllerAttribute.SubType.HasValue && controllerAttribute.SubType.Value == animationControllerSubType) { // For animation controllers, the 2 bytes are part of the data and identify an 'ushort' count field for n number of frames. if (controllerType.IsAnimationController()) { stream.Position -= 2; } } else // The subtype/count is part of the controller data, move back. { stream.Position -= 4; } } } // exits } // exits } else // Behavior controller, including names and size specifiers. { // Check if the stream contains a controller name. string readControllerName = PeekName(reader); // Substitute name of controller with the one we read from stream, if it does not match. if (controllerName == null || controllerName != readControllerName) { Debug.WriteLine("Controller name mismatch between '{0}' and '{1}', using '{1}'.", controllerName ?? "<unspecified>", readControllerName); controllerName = readControllerName; } profile = _controllerAssembly.GetControllerProfilesByName(controllerName).FirstOrDefault(); } // If we have found a profile to use, try to read the controller. if (profile != ControllerProfile.Unknown && !string.IsNullOrEmpty(controllerName)) { long controllerStartPosition = stream.Position; // Attempt to parse controller, starting with newest implementation. Type previousControllerType = null; Type controllerType = null; while (true) { try { if (_controllerAssembly.TryGetControllerType(controllerName, profile, out controllerType) && previousControllerType != controllerType) { Controller controller = _controllerFactory.CreateController(controllerType, false); IControllerSerializer cs = _controllerSerializerResolver.GetSerializer(controllerType); cs.Deserialize(stream, controller); return(controller); } previousControllerType = controllerType; } catch (Exception ex) { // Reset stream to beginning. stream.Position = controllerStartPosition; Debug.WriteLine(ex.Message); previousControllerType = controllerType; } // If we reach the oldest version of SH, we are finished. if (profile >= ControllerProfile.SH3) { break; } // Move to next profile. profile++; } } // If not implemented, return the raw bytes. stream.Position = currentPos; return(reader.ReadBytes((int)(stream.Length - currentPos))); }
/// <summary> /// Writes a controller to a stream. /// </summary> /// <param name="stream"></param> /// <param name="controller"></param> public void Write(Stream stream, object controller) { if (controller == null) { throw new ArgumentNullException(nameof(controller)); } // For fallback support, allow byte arrays/streams to be passed. // We simply write it as is. if (controller is byte[] byteBuffer) { stream.Write(byteBuffer, 0, byteBuffer.Length); return; } if (controller is Stream inputStream) { inputStream.CopyTo(stream); return; } using (var writer = new BinaryWriter(stream, FileEncoding.Default, true)) { Type controllerType = controller.GetType(); IControllerSerializer cs = _controllerSerializerResolver.GetSerializer(controllerType); if (!controllerType.IsBehaviorController()) { ControllerAttribute controllerAttribute = controllerType.GetCustomAttribute <ControllerAttribute>() ?? new ControllerAttribute(); if (controllerAttribute.SubType.HasValue) { writer.Write(controllerAttribute.SubType.Value); } if (controllerType.IsAnimationController() || !controllerAttribute.SubType.HasValue) { // Skip writing the count field, the serializer will take care of it. } else { writer.Write((ushort)0); } cs.Serialize(stream, (Controller)controller); return; } // Test if the type is from our controller assembly. if (!_controllerFactory.CanCreate(controllerType)) { throw new NotSupportedException("Invalid controller."); } // We don't know the size yet, so just write 0 for now. writer.Write(0); long startPos = stream.Position; cs.Serialize(stream, (Controller)controller); // After the controller is written, determine and write the size. long currentPos = stream.Position; stream.Position = startPos - 4; writer.Write((int)(currentPos - startPos)); // Restore position to the end of the controller. stream.Position = currentPos; } }
void Start() { onSelectedControllerChanged = (playerNumber, controllerNumber) => { if (!control(controllerNumber, playerNumber)) { switch (playerNumber) { case 1: Player1 = ControllerAttribute.NoController; break; case 2: Player2 = ControllerAttribute.NoController; break; } } }; }