【问题标题】:C# Interface (Call Method in Different Project/Assembly)C# 接口(不同项目/程序集中的调用方法)
【发布时间】:2008-12-16 01:54:29
【问题描述】:

下面的代码几乎总结了我想要实现的目标。

我们有一个包含许多不同项目的解决方案,但是我们需要能够从未引用的项目中调用项目中的方法(会导致循环引用)。

我已经发布了以前的问题,下面的代码几乎就是我使用接口提出的。我仍然不知道如何调用驻留在未引用的不同项目中的方法。

我不能创建接口的实例,它必须是一个类。但是如何创建未引用的类的实例。我不想为此使用反射。

代码是 C# 2.0

感谢任何帮助。

我需要在“GeneralMethod”(Class Raise)中放置什么代码才能执行“Listen”类中的“Update”方法?

// 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");
        }
    }
}

我可能应该澄清需要这样做的动机。也许有更好的方法....

我们有一个基础表单,所有其他项目都可以从中引用。作为示例,我们在项目加载时(从基础表单)传递一个包含各种设置的对象。

例如,如果设置对象有一些变量更改(设置对象填充在 baseform 中),我们希望加载的项目监听此更改并获取新的设置对象。

因为 baseform 引用了所有其他项目,我们需要让项目“监听”baseform 中的事件。

一清二楚:-)

【问题讨论】:

  • 另外...看看托管的可扩展性框架

标签: c# interface polymorphism


【解决方案1】:

我使用Activator.CreateInstance 来执行此操作。您从路径加载程序集,然后创建该类的实例。例如,您可以使用它在主机应用程序中加载小工具程序集,而主机在编译时不知道小工具。

示例伪代码(无错误处理)

为要加载的类创建一个接口:

public interface IRemote
{
     void Update();
}

那么你需要一个方法来加载Assembly并调用函数

现在这是一个使用所有这些的方法:

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

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

【讨论】:

    【解决方案2】:

    您需要 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 请求之前注册它的实现。

    一种更简单的方法是使用依赖注入框架为您管理这些东西,或者将您的项目重新排列成没有循环依赖的层。

    【讨论】:

      【解决方案3】:

      另一种选择是定义发布者订阅者模型。所以在你的链接项目(所有项目引用的项目)中,你可以有类似的东西(这是伪代码,所以不会自行编译,但会让你接近:

      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. 
         }
      }
      

      现在您可以为您的委托定义自己的签名,这样您就可以在您自己的自定义事件 args 类中传递您想要的任何状态。当每个听众醒来时,让他们注册他们的事件......您还应该实施取消注册。

      好处是您可以让应用程序的任何部分与任何其他部分进行通信,而无需它们完全耦合。

      已编辑

      这是一篇与我们使用的类似的文章他之前有一篇更好的文章,但我找不到:http://www.codeproject.com/KB/cs/eventpool.aspx

      以下是将泛型纳入账户的后续行动:http://www.codeproject.com/KB/cs/EventPool_Revisited.aspx

      【讨论】:

      • 乔希,谢谢……你的想法听起来不错。你能提供我们可以实现的更具体的代码吗?伪代码让我们接近但没有越界。
      • 在我们实现这个之后,有人在我的桌子上放了一篇 codeproject 文章......它与我们正在做的非常接近,让我为你找到它真是太可怕了......
      • 再次感谢链接。我已经下载了 eventpool 项目,我正在努力更好地理解它。太糟糕了,示例无法正常工作……有时您只需要看到它的实施即可获得“啊,这就是它的工作原理”的感觉。
      • 如果我有时间我会看看我是否可以收集一个样本。我从未使用过他的代码,但它看起来与我们的代码非常接近......如果你解决了这个问题,请告诉我,这样我就不会浪费任何时间......
      【解决方案4】:

      我可能应该澄清需要这样做的动机。也许有更好的方法....

      我们有一个基础表单,所有其他项目都可以从中引用。作为示例,我们在项目加载时(从基础表单)传递一个包含各种设置的对象。

      例如,如果设置对象有一些变量更改(设置对象填充在 baseform 中),我们希望加载的项目侦听此更改并获取新的设置对象。

      因为 baseform 引用了所有其他项目,我们需要让项目“监听”baseform 中的事件。

      清如泥。 :-)

      【讨论】:

      • 贾斯珀。请编辑您的问题并将此“信息”放在那里,如果您不这样做,此答案将被 SO 警察否决。
      【解决方案5】:

      简单的解决方案:

      项目 A 中的“Raise”类引用项目链接。所以它可以直接在定义的对象上调用方法。

      项目链接中的某些内容将被 Raise 类调用。然后它需要引发一个事件。

      “Listen”类可以监听该事件并做出反应。

      【讨论】:

      • 这听起来好像可以工作......但是如果在创建“Listen”实例之后创建了 Link 的实例,那么“Listen”如何订阅项目 Link 中的事件。据我了解,监听器需要订阅现有实例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多