Ваши приложения Windows Form не должны быть точкой, которую вы расширяете, exe-файлы должны быть просто оболочкой для запуска вашего процесса (насколько это возможно). Таким образом, этот ответ не отвечает вашей конкретной проблеме ссылок, поскольку это не считается хорошей практикой.
Все расширения должны быть сделаны для вашего кода или управляющих библиотек на основе известного интерфейса или контракта. Обычно процесс расширения таких приложений заключается в использовании альтернативных или дополнительных библиотек DLL, которые загружаются во время выполнения.
Скажем, у вас есть приложение под названием часы, которое должно отображать время.
Вы можете структурировать свое приложение с помощью набора контрактов (или интерфейсов) в ссылочной библиотеке DLL «Clock.Contracts.dll»:
public interface ITimeService
{
public string Name { get; }
public Date GetTime();
}
Затем у вас есть каждая реализация этого в другой DLL («Clock.LocalComputer.dll», «Clock.InternetTime.dll»
public class LocalTime : ITimeService
{
public string Name
{ get { return "Local Time"; }}
public Date GetTime()
{ return Date.Now; }
}
В пользовательском интерфейсе / EXE вы всегда ссылаетесь на интерфейс, а не вызываете реализацию.
Как получить экземпляр реализующего класса, используя Reflection, чтобы определить, реализует ли класс в DLL интерфейс, и Activator.CreateInstance, чтобы сгенерировать класс.
http://gsraj.tripod.com/dotnet/reflection.html
Существуют такие шаблоны, как Inversion of Control и Dependency Injection, которые помогают решать эти проблемы стандартизированным способом в вашем приложении. Сторонние библиотеки, такие как Замок Виндзор, Spring могут помочь. Поиск в Google даст вам некоторые материалы для чтения.
Я скажу, что может потребоваться некоторое время, чтобы полностью разобраться в этих вещах.