Интерфейс C# (метод вызова в другом проекте / сборке)

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

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

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

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

Код - C# 2.0

Любая помощь приветствуется.

Какой код мне нужно поместить в GeneralMethod (Class Raise), чтобы иметь возможность выполнить метод «Update» в классе «Listen»?

// Link Project
namespace Stack.Link
{
    public class Interface
    {
        public interface Update
        {
            void Update();
        }
    }
}

// Project A
// References Link only
namespace Stack.ProjA
{
    public class Raise
    {
        public void GeneralMethod()
        {
            // I want to place code in here to be able to execute 
            // "Update" method in ProjB.
            // Keep in mind that ProjA and ProjB only reference
            // Link Project            
        }
    }
}

// Project B
// References Link only
namespace Stack.ProjB
{
    public class Listen : Stack.Link.Interface.Update
    {
        public void Update()
        {
            // Do something here that is executed from ProjA
            Console.Write("Executed Method in ProjB");
        }
    }
}

Мне, вероятно, следует прояснить мотивацию, стоящую за этим. Возможно, есть способ получше ....

У нас есть базовая форма, из которой сделаны ссылки на все остальные проекты. В качестве примера мы передаем объект, который содержит различные настройки в проект при его загрузке (из базовой формы).

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

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

Ясно как грязь :-)

Также ... взгляните на структуру управляемой расширяемости

TimothyP 23.12.2008 16:33
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
13 393
5

Ответы 5

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

В ссылке на сборку:

public interface IThing { void Update(); }

public static class ThingRegistry {
  public static void RegisterThing<T>() where T : IThing { ... }

  public static T CreateThing<T>() where T : IThing { ... }
}

В сборке ProjA:

internal class Thing : IThing { public void Update() { ... } }

В сборке ProjB:

public class Listen { 
  public void UpdateThing() {
    ThingRegistry.CreateThing<IThing>().Update();
  }
}

Затем вы предоставляете какую-то конфигурацию, которая гарантирует, что ProjA зарегистрирует ее реализацию до того, как ProjB запросит ее.

Более простой способ - использовать фреймворк внедрения зависимостей для управления этим материалом или перегруппировать ваши проекты по уровням без циклических зависимостей.

Мне, вероятно, следует прояснить мотивацию, стоящую за этим. Возможно, есть способ получше ....

У нас есть базовая форма, из которой сделаны ссылки на все остальные проекты. В качестве примера мы передаем объект, который содержит различные настройки в проект при его загрузке (из базовой формы).

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

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

Ясно, как грязь. :-)

Джаспер. Пожалуйста, отредактируйте свой вопрос и поместите эту «информацию» туда, этот ответ БУДЕТ отклонен полицией SO, если вы этого не сделаете.

Binary Worrier 16.12.2008 11:11

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

public class EventBroadcaster {
   //use your singleton pattern of choice. This is not what I would reocmmend but its short
   private static EventBroadcaster Instance=new EventBroadcaster;

   public void RegisterForEvent(string key,Delegate del)
   {
    //Store the delegate in a dictionary<string,del>
   //You can also use multicast delegates so if your settings object changes notify all people who need it
    }

   public void FireEvent(string key,EventArgs e)
   {
   //Get the item and execute it. 
   }
}

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

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

Отредактировано

Вот статья о чем-то похожем на то, что мы использовали. У него была статья получше, но я пока не могу ее найти: http://www.codeproject.com/KB/cs/eventpool.aspx

Вот продолжение, в котором используются дженерики: http://www.codeproject.com/KB/cs/EventPool_Revisited.aspx

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

jasper 16.12.2008 07:02

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

JoshBerke 16.12.2008 07:24

спасибо еще раз за ссылки. Я загрузил проект eventpool и пытаюсь лучше его понять. Жаль, что образец не работает ... иногда все, что вам нужно, это увидеть его реализованным, чтобы получить ощущение «ах, вот как это работает».

jasper 16.12.2008 08:40

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

JoshBerke 16.12.2008 18:24

Простое решение:

Класс "Raise" в проекте Ссылки на проект Ссылка. Таким образом, он может вызывать методы непосредственно для определенных там объектов.

Что-то в ссылке на проект будет вызываться классом Raise. Затем ему нужно вызвать событие.

Класс «Слушать» может прослушивать это событие и реагировать.

похоже, что это могло бы сработать ... но как «Listen» подписаться на события в проекте Link, если экземпляр Link создается после создания экземпляра «Listen». Насколько я понимаю, слушателю нужно подписаться на существующий экземпляр.

jasper 17.12.2008 03:27

Для этого я использовал Activator.CreateInstance. Вы загружаете сборку по пути, а затем создаете экземпляр класса. Например, вы можете использовать это для загрузки сборок гаджетов в хост-приложение, где хост не знает о гаджетах во время компиляции.

Пример псевдокода (без обработки ошибок)

Создайте интерфейс для класса, который вы собираетесь загрузить:

public interface IRemote
{
     void Update();
}

Затем вам понадобится метод для загрузки сборки и вызова функции

Теперь вот способ использовать все это:

private void
   DoRemoteUpdate( string assemblyPath, string className )
{ 
   Assembly assembly   = Assembly.Load(assemblyPath); 
   Type     objectType = assembly.GetType(className); 

   remoteAssembly = (IRemote)Activator.CreateInstance(objectType); 
   remoteAssembly.Update(); 
}

Другие вопросы по теме