コード例 #1
0
        private static IRemoteTechAPIv1 InitializeAPI()
        {
            SafeHouse.Logger.Log(string.Format("Looking for RemoteTech"));
            var loadedAssembly = AssemblyLoader.loadedAssemblies.FirstOrDefault(a => a.assembly.GetName().Name.Equals(REMOTE_TECH_ASSEMBLY));

            if (loadedAssembly == null)
            {
                return(null);
            }
            SafeHouse.Logger.Log(string.Format("Found RemoteTech! Version: {0}.{1}", loadedAssembly.versionMajor, loadedAssembly.versionMinor));

            var type = ReflectUtil.GetLoadedTypes(loadedAssembly.assembly).FirstOrDefault(t => t.FullName.Equals(REMOTE_TECH_API)) ??
                       ReflectUtil.GetLoadedTypes(loadedAssembly.assembly).FirstOrDefault(t => t.FullName.Equals(ALT_REMOTE_TECH_API));

            if (type == null)
            {
                return(null);
            }

            SafeHouse.Logger.Log(string.Format("Found API! {0} ", type.Name));
            var methods = type.GetMethods();
            var api     = new RemoteTechAPI();

            try
            {
                foreach (var property in api.GetType().GetProperties())
                {
                    var method = methods.FirstOrDefault(m =>
                    {
                        if (m.Name.Equals(property.Name))
                        {
                            SafeHouse.Logger.Log(string.Format("Found Endpoint: {0}", m.Name));
                            return(true);
                        }
                        return(false);
                    });

                    if (method == null)
                    {
                        throw new ArgumentNullException(property.Name);
                    }

                    var del = Delegate.CreateDelegate(property.PropertyType, type, method.Name);
                    property.SetValue(api, del, null);
                }
            }
            catch (Exception e)
            {
                SafeHouse.Logger.Log("Error creating RemoteTech interface: " + e);
                return(null);
            }

            SafeHouse.Logger.Log("RemoteTech interface successfully created.");
            return(api);
        }
コード例 #2
0
        /// <summary>
        /// Ensure all classes implementing IDumper have the required static method in
        /// them, which is something the compiler cannot enforce itself because an Interface
        /// can't contain static things.
        /// </summary>
        /// Since interfaces don't enforce static things, this enforcement
        /// is being done via this Reflection check upon loading that will make nag messages
        /// if the CreateFromDump is missing on one of the classes.
        /// Note, if we ever need this check elsewhere for another "static" thing in an interface,
        /// It should be possible to make this more generic and make a library method here that
        /// takes any interface name and any method name and checks to see if it exists.
        public static void CheckIDumperStatics()
        {
            if (staticsAlreadyChecked)
            {
                return;
            }

            StringBuilder message = new StringBuilder(1000);

            Type dumperInterface = typeof(IDumper);

            // It's ugly to be checking ALL KSP mods here, but just in case someone
            // extends kOS in another mod, it's not safe to check ONLY kOS.dll and kOS.Safe.dll:
            Assembly[] allKSPAssemblies = AppDomain.CurrentDomain.GetAssemblies();

            // All the classes in which the class is derived from IDumper, and instances of the class are
            // actually constructable because it isn't Abstract:
            IEnumerable <Type> iDumperClasses = allKSPAssemblies.SelectMany(a => ReflectUtil.GetLoadedTypes(a)).Where(
                b => dumperInterface.IsAssignableFrom(b) && b.IsClass && !b.IsAbstract);

            List <string> offendingClasses = new List <string>();

            Type[] paramSignature = new Type[] { typeof(SafeSharedObjects), typeof(Dump) };
            foreach (Type t in iDumperClasses)
            {
                if (t.GetMethod("CreateFromDump", BindingFlags.Public | BindingFlags.Static, null, paramSignature, null) == null)
                {
                    offendingClasses.Add(t.FullName);
                }
            }

            if (offendingClasses.Count() > 0)
            {
                message.Append(
                    "kOS DEV TEAM ERROR.\n " +
                    "  This is a kOS source problem that the compiler\n" +
                    "  cannot check for because of limitations in C#.\n" +
                    "  (So we check it at runtime and give this error\n" +
                    "  if it's detected.)\n" +
                    "  \n" +
                    "  The following class(es) implement IDumper, but\n" +
                    "  lack the required CreateFromDump() static method\n" +
                    "  that we need all IDumper's to have:\n" +
                    "    ");
                message.Append(string.Join(", ", offendingClasses.ToArray()));
                Debug.AddNagMessage(Debug.NagType.NAGFOREVER, message.ToString());
            }
            staticsAlreadyChecked = true;
        }