Created
November 7, 2013 18:48
-
-
Save DevJohnC/7359810 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // Author: John Carruthers (johnc@frag-labs.com) | |
| // | |
| // Copyright (C) 2013 John Carruthers | |
| // | |
| // Permission is hereby granted, free of charge, to any person obtaining | |
| // a copy of this software and associated documentation files (the | |
| // "Software"), to deal in the Software without restriction, including | |
| // without limitation the rights to use, copy, modify, merge, publish, | |
| // distribute, sublicense, and/or sell copies of the Software, and to | |
| // permit persons to whom the Software is furnished to do so, subject to | |
| // the following conditions: | |
| // | |
| // The above copyright notice and this permission notice shall be | |
| // included in all copies or substantial portions of the Software. | |
| // | |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
| // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
| // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
| // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| // | |
| using System; | |
| using System.Collections.Generic; | |
| using System.Reflection; | |
| using System.Runtime.Remoting; | |
| namespace FragLabs.AdjutantOS.API.Modules.Domains | |
| { | |
| /// <summary> | |
| /// Provides common functionality in each domain. | |
| /// </summary> | |
| public class DomainController : DomainShareObject | |
| { | |
| /// <summary> | |
| /// Gets the current DomainController for the current AppDomain. | |
| /// </summary> | |
| public static DomainController Current { get; protected set; } | |
| /// <summary> | |
| /// Invoked before the DomainController is destroyed in preperation for the appdomain to be unloaded. | |
| /// </summary> | |
| public event EventHandler<EventArgs> BeforeDestroy; | |
| protected virtual void OnBeforeDestroy() | |
| { | |
| var handler = BeforeDestroy; | |
| if (handler != null) handler(this, EventArgs.Empty); | |
| } | |
| /// <summary> | |
| /// Gets the DomainManager responsible for the DomainController. | |
| /// </summary> | |
| public DomainManager Manager { get; protected set; } | |
| /// <summary> | |
| /// Registered assemblies for type resolution. | |
| /// </summary> | |
| private readonly List<Assembly> _assemblies = new List<Assembly>(); | |
| /// <summary> | |
| /// Gets the appdomain the DomainController instance is loaded in. | |
| /// </summary> | |
| public AppDomain AppDomain { get { return AppDomain.CurrentDomain; } } | |
| /// <summary> | |
| /// Is main domain? | |
| /// </summary> | |
| internal bool IsMainDomain { get; set; } | |
| /// <summary> | |
| /// Creates a new instance of DomainController. | |
| /// </summary> | |
| public DomainController() | |
| { | |
| IsMainDomain = true; | |
| Current = this; | |
| Manager = DomainManager.Current; | |
| Manager.Add(this); | |
| } | |
| /// <summary> | |
| /// Creates a new instance of DomainController with a specific DomainManager. | |
| /// </summary> | |
| /// <param name="manager">DomainManager responsible for the DomainController.</param> | |
| public DomainController(DomainManager manager) | |
| { | |
| IsMainDomain = true; | |
| Current = this; | |
| Manager = manager; | |
| Manager.Add(this); | |
| } | |
| /// <summary> | |
| /// Destroys the domain controller in preperation for unloading the domain. | |
| /// </summary> | |
| public void Destroy() | |
| { | |
| OnBeforeDestroy(); | |
| } | |
| /// <summary> | |
| /// Initialize. | |
| /// </summary> | |
| public void Initialize(DomainManager manager) | |
| { | |
| DomainManager.Current = manager; | |
| DomainManager.Initialized = true; | |
| IsMainDomain = false; | |
| } | |
| /// <summary> | |
| /// Add an assembly for type resolution. | |
| /// </summary> | |
| /// <param name="asm"></param> | |
| public void AddAssembly(Assembly asm) | |
| { | |
| _assemblies.Add(asm); | |
| } | |
| /// <summary> | |
| /// Loads an assembly into the domain. | |
| /// </summary> | |
| /// <param name="filePath"></param> | |
| /// <param name="addToResolutionAssemblies"></param> | |
| public void LoadAssembly(string filePath, bool addToResolutionAssemblies = true) | |
| { | |
| var asm = Assembly.LoadFile(filePath); | |
| if (addToResolutionAssemblies) | |
| AddAssembly(asm); | |
| } | |
| /// <summary> | |
| /// Creates a new instance of an object and marshals the object across appdomains. | |
| /// </summary> | |
| /// <param name="domainType"></param> | |
| /// <param name="ctorArgs"></param> | |
| /// <returns></returns> | |
| public object CreateMarshalledReference(DomainType domainType, params object[] ctorArgs) | |
| { | |
| return CreateMarshalledReference(domainType.Controller, domainType, ctorArgs); | |
| } | |
| /// <summary> | |
| /// Creates a new instance of an object and marshals the object across appdomains. | |
| /// </summary> | |
| /// <param name="controller"></param> | |
| /// <param name="domainType"></param> | |
| /// <param name="ctorArgs"></param> | |
| /// <returns></returns> | |
| public object CreateMarshalledReference(DomainController controller, DomainType domainType, params object[] ctorArgs) | |
| { | |
| var objRef = controller.CreateInstance(domainType, ctorArgs); | |
| return RemotingServices.Unmarshal(objRef); | |
| } | |
| /// <summary> | |
| /// Creates an ObjRef for an object in the foreign AppDomain. | |
| /// </summary> | |
| /// <param name="domainType"></param> | |
| /// <param name="ctorArgs"></param> | |
| /// <returns></returns> | |
| public ObjRef CreateInstance(DomainType domainType, params object[] ctorArgs) | |
| { | |
| if (!domainType.Type.IsSubclassOf(typeof(MarshalByRefObject))) | |
| throw new Exception("Type must be subclass of MarshalByRefObject"); | |
| var obj = Activator.CreateInstance(domainType.Type, ctorArgs) as MarshalByRefObject; | |
| return RemotingServices.Marshal(obj); | |
| } | |
| /// <summary> | |
| /// Attempts to resolve a domain type. | |
| /// </summary> | |
| /// <param name="typeName"></param> | |
| /// <returns></returns> | |
| public DomainType ResolveType(string typeName) | |
| { | |
| var type = Type.GetType(typeName); | |
| if (type != null) | |
| return type.GetDomainType(); | |
| foreach (var asm in _assemblies) | |
| { | |
| type = asm.GetType(typeName); | |
| if (type != null) | |
| return type.GetDomainType(); | |
| } | |
| return null; | |
| } | |
| /// <summary> | |
| /// Attempts to get a DomainType definition for an object. | |
| /// </summary> | |
| /// <param name="obj"></param> | |
| /// <returns></returns> | |
| public DomainType GetDomainType(object obj) | |
| { | |
| if (RemotingServices.IsTransparentProxy(obj)) | |
| return null; | |
| return obj.GetType().GetDomainType(); | |
| } | |
| /// <summary> | |
| /// Searches the domain for subtypes of the provided parent type. | |
| /// </summary> | |
| /// <param name="parentType"></param> | |
| /// <returns></returns> | |
| public DomainType[] FindSubTypes(Type parentType) | |
| { | |
| var ret = new List<DomainType>(); | |
| foreach (var asm in _assemblies) | |
| { | |
| foreach (var type in asm.GetTypes()) | |
| { | |
| if (type.IsSubclassOf(parentType)) | |
| { | |
| ret.Add(new DomainType(type)); | |
| } | |
| } | |
| } | |
| return ret.ToArray(); | |
| } | |
| /// <summary> | |
| /// Searches the domain for types that implement a given interface type. | |
| /// </summary> | |
| /// <param name="interfaceType"></param> | |
| /// <returns></returns> | |
| public DomainType[] FindTypesThatImplement(Type interfaceType) | |
| { | |
| var ret = new List<DomainType>(); | |
| foreach (var asm in _assemblies) | |
| { | |
| foreach (var type in asm.GetTypes()) | |
| { | |
| foreach (var iface in type.GetInterfaces()) | |
| { | |
| if (iface.Equals(interfaceType)) | |
| { | |
| ret.Add(new DomainType(type)); | |
| } | |
| if (iface.IsGenericType) | |
| { | |
| var genericType = iface.GetGenericTypeDefinition(); | |
| if (genericType.Equals(interfaceType)) | |
| { | |
| ret.Add(new DomainType(type)); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return ret.ToArray(); | |
| } | |
| /// <summary> | |
| /// Invokes an Action delegate on the main application domain. | |
| /// <para>If the delegate is not in a library loaded in the main application domain the Action should be made domain safe with a DomainCallback.</para> | |
| /// </summary> | |
| /// <param name="action"></param> | |
| public void InvokeAction(Action action) | |
| { | |
| action(); | |
| } | |
| /// <summary> | |
| /// Invokes an Action delegate on the main application domain. | |
| /// <para>If the delegate is not in a library loaded in the main application domain the Action should be made domain safe with a DomainCallback.</para> | |
| /// </summary> | |
| /// <typeparam name="T1"></typeparam> | |
| /// <param name="action"></param> | |
| /// <param name="arg1"></param> | |
| public void InvokeAction<T1>(Action<T1> action, T1 arg1) | |
| { | |
| action(arg1); | |
| } | |
| /// <summary> | |
| /// Invokes an Action delegate on the main application domain. | |
| /// <para>If the delegate is not in a library loaded in the main application domain the Action should be made domain safe with a DomainCallback.</para> | |
| /// </summary> | |
| /// <typeparam name="T1"></typeparam> | |
| /// <typeparam name="T2"></typeparam> | |
| /// <param name="action"></param> | |
| /// <param name="arg1"></param> | |
| /// <param name="arg2"></param> | |
| public void InvokeAction<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2) | |
| { | |
| action(arg1, arg2); | |
| } | |
| /// <summary> | |
| /// Invokes an Action delegate on the main application domain. | |
| /// <para>If the delegate is not in a library loaded in the main application domain the Action should be made domain safe with a DomainCallback.</para> | |
| /// </summary> | |
| /// <typeparam name="T1"></typeparam> | |
| /// <typeparam name="T2"></typeparam> | |
| /// <typeparam name="T3"></typeparam> | |
| /// <param name="action"></param> | |
| /// <param name="arg1"></param> | |
| /// <param name="arg2"></param> | |
| /// <param name="arg3"></param> | |
| public void InvokeAction<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3) | |
| { | |
| action(arg1, arg2, arg3); | |
| } | |
| /// <summary> | |
| /// Invokes a Func delegate on the main application domain. | |
| /// <para>If the delegate is not in a library loaded in the main application domain the Action should be made domain safe with a DomainCallback.</para> | |
| /// </summary> | |
| /// <typeparam name="TResult"></typeparam> | |
| /// <param name="func"></param> | |
| public TResult InvokeFunc<TResult>(Func<TResult> func) | |
| { | |
| return func(); | |
| } | |
| /// <summary> | |
| /// Invokes a Func delegate on the main application domain. | |
| /// <para>If the delegate is not in a library loaded in the main application domain the Action should be made domain safe with a DomainCallback.</para> | |
| /// </summary> | |
| /// <typeparam name="TResult"></typeparam> | |
| /// <typeparam name="T1"></typeparam> | |
| /// <param name="func"></param> | |
| public TResult InvokeFunc<T1, TResult>(Func<T1, TResult> func, T1 arg1) | |
| { | |
| return func(arg1); | |
| } | |
| /// <summary> | |
| /// Invokes a Func delegate on the main application domain. | |
| /// <para>If the delegate is not in a library loaded in the main application domain the Action should be made domain safe with a DomainCallback.</para> | |
| /// </summary> | |
| /// <typeparam name="TResult"></typeparam> | |
| /// <typeparam name="T1"></typeparam> | |
| /// <typeparam name="T2"></typeparam> | |
| /// <param name="func"></param> | |
| public TResult InvokeFunc<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2) | |
| { | |
| return func(arg1, arg2); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment