Интерфейс C # (метод вызова в другом проекте / сборке) - PullRequest
1 голос
/ 16 декабря 2008

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

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

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

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

Код 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");
        }
    }
}

Я, наверное, должен уточнить мотивы необходимости делать это. Возможно, есть лучший способ ....

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

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

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

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

Ответы [ 5 ]

2 голосов
/ 16 декабря 2008

Я использовал 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(); 
}
1 голос
/ 16 декабря 2008

Вам необходим проект 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 запросит ее.

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

0 голосов
/ 16 декабря 2008

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

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

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

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

0 голосов
/ 16 декабря 2008

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

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

0 голосов
/ 16 декабря 2008

Я, наверное, должен уточнить мотивы необходимости сделать это. Возможно, есть лучший способ ....

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

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

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

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

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