C# 接口(不同项目/程序集中的调用方法)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/370286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Interface (Call Method in Different Project/Assembly)
提问by
The code below pretty much sums up what I want to achieve.
下面的代码几乎总结了我想要实现的目标。
We have a solution which comprises many different projects however we have a need to be able to call methods in projects from projects which are not referenced (would cause circular reference).
我们有一个包含许多不同项目的解决方案,但是我们需要能够从未引用的项目中调用项目中的方法(会导致循环引用)。
I have posted previous questions and the code below is pretty much what I have come up with using interfaces. I still do not know how I can call a method that resides in a different project that is not referenced.
我已经发布了以前的问题,下面的代码几乎是我使用接口提出的。我仍然不知道如何调用驻留在未引用的不同项目中的方法。
I cannot create an instance of the interface, it has to be a class. But how can I create an instance of a class that is not referenced. I do not want to use reflection for this.
我无法创建接口的实例,它必须是一个类。但是如何创建一个未被引用的类的实例。我不想为此使用反射。
Code is C# 2.0
代码是 C# 2.0
Any help is appreciated.
任何帮助表示赞赏。
What code do I need to place in "GeneralMethod" (Class Raise) to be able to execute the "Update" method in Class "Listen" ?
我需要在“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");
}
}
}
I should probably clarify the motivation behind needing to do this. Perhaps there is a better way ....
我可能应该澄清需要这样做的动机。也许有更好的方法......
We have a baseform from which all other projects are referenced. As an example we pass an object which contains various settings to the project when it is loaded (from the baseform).
我们有一个基础表格,所有其他项目都从中引用。作为示例,我们在加载项目时(从基础表单)将包含各种设置的对象传递给项目。
If for example, the settings object has some variables change (settings object populated in baseform), we would like the loaded project to listen for this change and obtain a new settings object.
例如,如果设置对象有一些变量更改(设置对象填充在 baseform 中),我们希望加载的项目侦听此更改并获取新的设置对象。
Because the baseform references all the other projects, we need to have the projects "listen" for events in the baseform.
因为 baseform 引用了所有其他项目,所以我们需要让项目“监听”baseform 中的事件。
Clear as mud :-)
像泥一样清澈:-)
回答by Andrew Kennan
You need the Link project to provide a way of registering and constructing concrete implementations of the interfaces. Then ProjA will register an implementation and ProjB can request it.
您需要 Link 项目来提供一种注册和构建接口具体实现的方法。然后 ProjA 将注册一个实现,ProjB 可以请求它。
In assembly link:
在组装链接中:
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 { ... }
}
In assembly ProjA:
在组装 ProjA 中:
internal class Thing : IThing { public void Update() { ... } }
In assembly ProjB:
在组装 ProjB 中:
public class Listen {
public void UpdateThing() {
ThingRegistry.CreateThing<IThing>().Update();
}
}
Then you provide some sort of configuration that makes sure ProjA registers it's implementation before ProjB requests it.
然后您提供某种配置以确保 ProjA 在 ProjB 请求它之前注册它的实现。
An easier way is to use a dependency injection framework to manage that stuff for you or rearrange your projects into layers with no circular dependencies.
一种更简单的方法是使用依赖注入框架来为你管理这些东西,或者将你的项目重新排列成没有循环依赖的层。
回答by Andrew Kennan
I should probably clarify the motivation behind needing to do this. Perhaps there is a better way ....
我可能应该澄清需要这样做的动机。也许有更好的方法......
We have a baseform from which all other projects are referenced. As an example we pass an object which contains various settings to the project when it is loaded (from the baseform).
我们有一个基础表格,所有其他项目都从中引用。作为示例,我们在加载项目时(从基础表单)将包含各种设置的对象传递给项目。
If for example, the settings object has some variables change (settings object populated in baseform), we would like the loaded project to listen for this change and obtain a new settings object.
例如,如果设置对象有一些变量更改(设置对象填充在 baseform 中),我们希望加载的项目侦听此更改并获取新的设置对象。
Because the baseform references all the other projects, we need to have the projects "listen" for events in the baseform.
因为 baseform 引用了所有其他项目,所以我们需要让项目“监听”baseform 中的事件。
Clear as mud. :-)
清如泥。:-)
回答by JoshBerke
Another option would to be define a a publisher subscriber model. So in your link project (The project which all projects reference) you could have something like (This is psuedo code so will not compile on its own but get you close:
另一种选择是定义一个发布者订阅者模型。因此,在您的链接项目(所有项目引用的项目)中,您可以拥有类似的内容(这是伪代码,因此不会自行编译,但会让您关闭:
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.
}
}
Now you can define your own signature for your delegate so you can pass whatever state you want in your own custom event args class. When each listern wakes up have them Register for their events...you should also implement an unregister.
现在您可以为您的委托定义您自己的签名,以便您可以在您自己的自定义事件 args 类中传递您想要的任何状态。当每个侦听器唤醒时,让他们注册他们的事件......你还应该实现一个取消注册。
the nice thing is you can have any part of your app talking to any other part without them being coupled at all.
好消息是你可以让你的应用程序的任何部分与任何其他部分交谈,而它们根本没有耦合。
Edited
已编辑
Here's an article on something simillar to what we used He had a better article before but I can;t find it yet: http://www.codeproject.com/KB/cs/eventpool.aspx
这是一篇关于类似于我们使用的东西的文章他以前有一篇更好的文章,但我找不到;还没有找到:http: //www.codeproject.com/KB/cs/eventpool.aspx
Here's a followup taking generics into accoutn: http://www.codeproject.com/KB/cs/EventPool_Revisited.aspx
这是将泛型纳入账户的后续行动:http: //www.codeproject.com/KB/cs/EventPool_Revisited.aspx
回答by Nigel Hawkins
Simple solution:
简单的解决方案:
Class "Raise" in project A references project Link. So it can call methods directly on objects defined there.
项目 A 中的“Raise”类引用项目链接。所以它可以直接在那里定义的对象上调用方法。
Something in project link is going to be called by class Raise. It then needs to raise an event.
项目链接中的某些内容将由类 Raise 调用。然后它需要引发一个事件。
Class "Listen" can listen for that event and react.
“Listen”类可以监听该事件并做出反应。
回答by Marcus Erickson
I used Activator.CreateInstance
to do this. You load the assembly from a path and then create an instance of the class. For example, you could use this to load gadgets assemblies in a host application where the host doesnt know about the gadgets at compile time.
我曾经Activator.CreateInstance
这样做过。从路径加载程序集,然后创建类的实例。例如,您可以使用它在宿主应用程序中加载小工具程序集,其中宿主在编译时不知道小工具。
Sample Pseudo Code (no error handling)
示例伪代码(无错误处理)
Create an interface for the class you are going to load:
为要加载的类创建一个接口:
public interface IRemote
{
void Update();
}
Then you need a method to load the Assembly and call the function
然后你需要一个方法来加载程序集并调用函数
Now here is a method to use all this:
现在这是一种使用所有这些的方法:
private void
DoRemoteUpdate( string assemblyPath, string className )
{
Assembly assembly = Assembly.Load(assemblyPath);
Type objectType = assembly.GetType(className);
remoteAssembly = (IRemote)Activator.CreateInstance(objectType);
remoteAssembly.Update();
}