Ссылка на класс, который не был создан / еще не создан - PullRequest
0 голосов
/ 29 мая 2018

У меня есть приложение Winforms, которое разработано для интеграции с внешними программными пакетами.Это приложение считывает данные из этих пакетов и отправляет их на наш сервер, где пользователи входят в систему и используют наше приложение (приложение).

public abstract ClassToImplement
{
    public abstract void DefinedMethod1();
    public abstract void DefinedMethod2();
}

Когда мы разрабатывали приложение, оно должно было выполнить 95% работ по интеграции.оставшиеся 5% (класс реализации / App2) разрабатываются консультантом, который знаком со сторонним программным обеспечением.

public class Implemented : ClassToImplement{
    public override void DefinedMethod1(...);
    public override void DefinedMethod2(...);
}

«Приложение» выводит библиотеку классов, на которую затем ссылаются в реализации (приложение 2).В нашем дизайне мы создали абстрактный класс и определили методы.Идея заключалась в том, что консультант загрузит репозиторий для класса реализации и включит приложение в качестве справочного материала.Затем они напишут необходимый код для методов, которые они реализуют, скомпилируют и «вуаля!»

По очевидным причинам я не хочу делиться исходным проектом с внешними разработчиками, иначе я бы просто поделилсяполное решение и использовать одно приложение, и, хотя я знаю, что они могут многое увидеть со ссылкой на DLL, нам просто все проще контролировать.

Проблема заключается в приложении: основной алгоритм приложениянеобходимо создать экземпляр класса реализации, а затем программа будет работать идеально.

в Form1.cs приложения:

ClassToImplement impObj = new Implemented();
impObj.DefinedMethod1();
impObj.DefinedMethod2();

Проблема, с которой я сталкиваюсь, заключается в том, что я не могу собрать приложение длявывести DLL без создания экземпляра класса.Я не могу создать экземпляр реализованного класса, поскольку у меня нет кода (пока).

Было бы здорово узнать, как добиться такой абстракции с зависимостью от (пока) неписаного кода, а также, каков технический термин для того, что я пытаюсь сделать?

Ответы [ 4 ]

0 голосов
/ 29 мая 2018

Во-первых, я думаю, что вам нужно внедрить правильную систему плагинов, если вы не хотите делиться своим кодом с другими разработчиками.

Во-вторых, вы должны кодировать против своего интерфейса, а не против его реализации.Во-первых, потому что у вас его нет, а во-вторых, потому что вы можете захотеть переключать реализации для разных сторонних программ.

Если вам нужен экземпляр для тестирования или чего-то подобного, вы можете использовать рукописный макет или фальшивый фреймворк.Если позже вам понадобится реальный экземпляр (когда это сделали другие разработчики), вы можете использовать для создания какой-то шаблон проектирования, например, шаблон фабрики или другие.Старайтесь избегать нового ключевого слова, если хотите позже изменить реализацию.

0 голосов
/ 29 мая 2018

Процесс, который вы ищете, часто называют stubbing .В этом случае вы решили инкапсулировать функции интеграции в библиотеке, а не в веб-службах, но принцип тот же.

Идея заключалась в том, что консультант загрузит репозиторий для класса реализации.и включите приложение в качестве ссылки.

Звучит так, как будто вы неправильно установили отношения зависимости.Если код консультанта ссылается на ваше приложение, то ваше приложение не может ссылаться на него - это будет круговая зависимость.Вместо этого, добавьте в ваше приложение что-то более похожее на следующее:

App | | App.Integration.Contracts ^ ^ | | | App.Integration.Stub | App.Integration

Абстрактный класс - он также может быть просто интерфейсом в C # - находится в сборке Contracts.Это единственная скомпилированная зависимость вашего приложения.Затем во время выполнения использует конфигурацию для загрузки заглушки или полной реализации с использованием контейнера IoC.Примером является Unity , для которого вам потребуется API конфигурации .Укажите истинный тип для использования в файле конфигурации и измените только на , чтобы обновить приложение для использования всех функций.

0 голосов
/ 29 мая 2018

Чтобы заставить его просто «работать», используйте Func, который возвращает экземпляр абстрактного класса.

В вашем тайном репо:

//Your "App" DLL Project
public abstract class ClassToImplement
{
    public abstract void DefinedMethod1();
    public abstract void DefinedMethod2();
}


public class App : Form
{

    public App(Func<ClassToImplement> initiator)
    {
        InitializeComponent();

        ClassToImplement ci = initiator.Invoke();
        ci.DefinedMethod1();
        ci.DefinedMethod2();
    }
}


//This is in a separate project which will be your startup project internally

public class Dummy : ClassToImplement
{
    public override void DefinedMethod1(){}
    public override void DefinedMethod2(){}
}

public class Program
{
    public static void Main()
    {
        Application.Run(new App(()=> new Dummy()));
    }
}

В репо с консультантом:

// In the repo which is shared with the consultant
// This will be the startup project on the build server, and when the consultant is testing.
public class Implementation : ClassToImplement
{
    public override void DefinedMethod1(){}
    public override void DefinedMethod2(){}
}

public class Program
{
    public static void Main()
    {
        Application.Run(new App(()=> new Implementation()));
    }
}

Вкл.ваш сервер сборки, вы можете извлечь из обоих репозиториев, и установить стартовый проект как тот, который предоставляется консультанту.Но когда вы тестируете и разрабатываете внутренне, вы устанавливаете проект запуска на свою версию с реализацией, которая ничего не делает.

В качестве примечания, если вы думаете, что то, что вы делаете, должно быть защищено отКонсультанты, которые подписали соглашение о конфиденциальности, обязательно запутывайте, когда вы делаете релиз.

0 голосов
/ 29 мая 2018

Обычно это двухэтапный процесс:

  1. Найдите и загрузите сборку / dll:

    Assembly assembly = Assembly.LoadFrom(DLL);
    
  2. Выполните реализациюкласс:

    Type type = assembly.GetType(FullNameOfImplemented);
    AppInstance = (ClassToImplement)Activator.CreateInstance(type, parameters);
    
...