0

Im relatively new to C# and am not sure if this is possible using this platform. I wish to have a program which is able to pull arbitrary classes from a remote server and use them to extend functionality of the program.

I am testing with two seperate projects, one contains a program which contains about 20 classes derived from a single abstract class which have been serialized individually.

The other project contains a program which has a definition of the abstract base class and attempts to deserialize the derived classes from the remote location in order to extend functionality

I am unable to get the deserializing program to be able to successfully deserialize and execute any of the derived classes.

//the files in Project1
//ABC file
namespace Project1
{
    [Serializable] 
    public abstract class BaseClass
    {
        public abstract void RunAndWait();
    }
}

//Derived class file
namespace Project1
{
    [Serializable]
    public class DerivedClass : BaseClass
    {
        public abstract void RunAndWait()
        {
            //do stuff here
        }
    }
}

//Serialize file contents
namespace Project1
{
    public class SerializeClass
    {

        public static void Serialize(BaseClass c)
        {
            string path = "/some/path/DERIVEDCLASS.bin"
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream(path,FileMode.Create,FileAccess.Write);
            formatter.Serialize(stream, c);
            stream.Close();
        }
    }
}

In another project I wish to be able to dynamically extend the functionality of the program by deserializing classes as needed.

//the files in project2
//ABC file in project2
namespace Project2
{
    [Serializable] 
    public abstract class BaseClass
    {
        public abstract void RunAndWait();
        //stuff goes here
    }
}

//main file in project2
namespace Project2
{
    class Program
    {
        static void Main(string[] args)
        {
            string readfile = "/some/path/DERIVEDCLASS.bin";
            FileStream fs = new FileStream(readfile, FileMode.Open);
            try
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Binder = new PreMergeToMergedDeserializationBinder();
/*this is what fails*/ 
                BaseTechClass c = (BaseTechClass) formatter.Deserialize(fs);
                c.RunAndWait();
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed. Reason: " + e.Message);
                throw;
            }
            finally
            {
                fs.Close();
            } 
        }
    }
}

//Read i needed to do a serialization binder to rename the assembly
sealed class PreMergeToMergedDeserializationBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        Type typeToDeserialize = null;
        String exeAssembly = Assembly.GetExecutingAssembly().FullName;
        Console.WriteLine("exeAssembly is: "+exeAssembly);
        typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
            typeName, exeAssembly));
        Console.WriteLine("type is: "+typeToDeserialize.ToString());
        return typeToDeserialize;
    }
}

I am getting errors such as Failed to deserialize. Reason: Unable to find assembly

I could use some guidance as to what is going wrong. the assembly renaming is not working and I am unsure if what i want to do is even possible in C# without include the entire DLL that has every derived class definition I want to de serialize and use.

james reeves
  • 173
  • 1
  • 5
  • "Serialization" generally refers to just data - not instructions/functions/methods/libraries, see https://stackoverflow.com/questions/2767893/are-methods-also-serialized-along-with-the-data-members-in-net - that said, you can implement what you're after by sending the dependent assembly down the pipe and loading it inside your `SerializationBinder` - of course this introduces massive security vulnerabilities so please be careful and never load or run untrusted code (i.e. make sure you sign all of your assemblies!) – Dai Mar 11 '20 at 03:28
  • This sounds like what I would like to do, dai. Could you provide some additional information? I am most interested in modularizing the classes and not sending over one monolithic DLL with every class in it. – james reeves Mar 11 '20 at 03:46
  • The class `Project1.BaseClass` is not the same as `Project2.BaseClass`. And even if you used the `Project1` namespace in Project 2 they would not be the same classes. The bottom-line is you need to use the same class in the same assembly to serialize and deserialize an object using the `BinaryFormatter`. – Enigmativity Mar 11 '20 at 03:48
  • You may want to read on https://www.bing.com/search?q=.net+terrarium for example... Keep in mind that as @Dai pointed out idea of loading untrusted code into your process is... questionable at best. There is really no good sandboxing for such approach. There is probably more plausible solution out there with something like Docker containers and remoting... but that *may* be a bit... too much. – Alexei Levenkov Mar 11 '20 at 04:42
  • 1
    @AlexeiLevenkov One of my company's products I built does use remote-code-execution, but it only runs code signed with a PKI signature that's only exists on a smart-card on my desk - and if I lose that card then all of our users are going to have to reinstall a new build of our software with a new public key - and the entire Win32 process runs with minimal privileges. I still felt a bit dirty implementing this solution though! – Dai Mar 11 '20 at 04:52

0 Answers0