Q:

Loading different Libraries with same Functions dynamically

I have a program which has a reference to an external DLL:
magic.externalFunctions.sql.dll

depending on the target system I might need the following instead:
magic.externalFunctions.nosql.dll

These DLLs are external libraries who offer the same functionality. Even the public methods and properties are the same. But they do not have a combined Interface or base class. 
Now I need to chose between these two libraries depending on the target system. If they would have an Interface in common I would do something like:
public class DoDatabaseStuff() {
    private IMagic _magic
    public DoDatabaseStuff(bool useNoSql) {
       if (useNoSql) {
         _magic=new SqlMagic();
       } else {
         _magic=new NoSqlMagic();
       }
       myTable=_magic.Table.Create("CustomerTable");
       myTable.Columns.Add(typeof(int),"ID");
       myTable.Columns.Add(typeof(string),"Name");
   }
}

Is there any way to solve this without using an excessive amount of reflection? I still want to use something like myTable.Columns.Add() instead of tableType.GetMethod("Add").Invoke()...
I also do not want to use conditions in the csproj using different build configurations. While this does work in theory, it gets distroyed every time the csproj changes automatically(e.g. a nuget-package updates)

A:

When you are confronted with bad design that you can not change, a good way to go is to keep that design out of your code. In this case that means that you should create the common interface that your external assemblies are lacking.
You can use adapters to provide a unified interface to keep the initial design flaw out of the core of your code.
You start with creating abstractions for the original classes you want to access:
public interface IMagic {
    ITable CreateTable(string name);
}

public interface ITable {
    void AddColumn(Type type, string name);
}

Then you provide adapters:
class SqlMagicAdapter : IMagic {
    SqlMagic m_innerMagic = new SqlMagic();

    ITable CreateTable(string name) {
        return new SqlTableAdapter(m_innerMagic.Table.Create(name));
    }
}

class SqlTableAdapter : ITable {
    SqlTable m_innerTable;
    public SqlTableAdapter(SqlTable innerTable) {
        m_innerTable = innerTable;
    }
    void AddColumn(Type type, string name) {
        m_innerTable.Columns.Add(type, name);
    }
}

class NoSqlMagicAdapter : IMagic {
    NoSqlMagic m_innerMagic = new NoSqlMagic();

    ITable CreateTable(string name) {
        return new NoSqlTableAdapter(m_innerMagic.Table.Create(name));
    }
}

class NoSqlTableAdapter : ITable {
    NoSqlTable m_innerTable;
    public NoSqlTableAdapter(NoSqlTable innerTable) {
        m_innerTable = innerTable;
    }
    void AddColumn(Type type, string name) {
        m_innerTable.Columns.Add(type, name);
    }

With a factory method you can return the respective adapter:
public static class MagicFactory {
    public static IMagic GetMagic(bool useNoSql) {
        if (useNoSql) {
            return new NoSqlMagic();
        }
        else {
            return new SqlMagic();
        }
    }
}

Your core code can be kept clean by only using the abstractions returned by the factory:
public class DoDatabaseStuff() {
    private IMagic _magic
    public DoDatabaseStuff(bool useNoSql) {
       _magic = MagicFactory.GetMagic(useNoSql);
       ITable myTable = _magic.CreateTable("CustomerTable");
       myTable.AddColumn(typeof(int), "ID");
       myTable.AddColumn(typeof(string), "Name");
   }
}

An added advantage is that you are also ready for any future changes, for example yet another updated external library that is not compatible to the previous ones. You can easily support these new functionalities without changing your core code.

