我有一个非常基本的问题(我不知道为什么我无法直接思考)。
我正在尝试做一些多态性。
我的界面看起来像这样:
Public interface Iplugin
{
void doSomthing(string _str);
}
我还有一些插件类可以填充这个界面
public class plugin1:Iplugin
{
void doSomthing(string _str)
{
if (_str=="1")
{
// do somthing 1
}
}
}
public class plugin2:Iplugin
{
void doSomthing(string _str)
{
if (_str=="2")
{
// do somthing 2
}
}
}
public class plugin3:Iplugin
{
void doSomthing(string _str)
{
if (_str=="3")
{
// do somthing 3
}
}
}
所以我有主类,我希望它能调用所有插件
但是我想保存OCP(开放 - 封闭原则)所以如果我将来添加另一个插件类,主类将不会改变。
这是主要的课程
public class mainApp
{
Iplugin _context;
mainApp()
{
_context= new //new what??
}
bool func(string str)
{
_context.doSomthing(str);//I would like it to invoke all the plug in and also a future plugins that I will add
}
}
答案 0 :(得分:2)
当然,要创建特定的Iplugin
,您需要了解实现类型。查看Factory Pattern。
答案 1 :(得分:2)
对于这样的情况,我喜欢使用Factory Pattern。您可以轻松地将其与某些属性和反射魔法相结合,以构建可用插件的存储库
[PluginAttribute("myPlugin")]
class MyPlugin : IPlugin
现在工厂最初检查所有已加载程序集中的所有类,并搜索该属性并将类型和插件字符串标识符存储在字典中。
class PluginFactory
{
static Iplugin CreatePlugin(string aName)
{
return Activator.CreateInstance( sRegisteredPlugins[aName]);
}
private static Dictionary<string, Type> sRegisteredPlugins;
}
答案 2 :(得分:1)
您可以添加一个集合来存储插件。集合可以在一个地方填充,然后传递给另一个方法,该方法只是迭代所有插件并调用它们。这样,它完全独立于集合中的插件类型。
正如@Ian所提到的,您需要声明doSomthing
virtual
才能使其正常工作。
public class mainApp
{
mainApp()
{
List<Iplugin> plugins = new ArrayList<Iplugin>;
...
plugins.add(new plugin1());
...
plugins.add(new plugin3());
...
func(plugins, "1");
...
func(plugins, "7");
}
bool func(List<IPlugin> plugins, string str)
{
foreach (IPlugin plugin in plugins) {
plugin.doSomthing(str);
}
}
}
这是Dependency Injection的一个简单例子,它是多态的一个众所周知的应用(好吧,为了使它成为真正的DI,你应该把func
放到另一个类中)。为了使您的代码更加灵活,并将插件的创建与其使用分离,您还可以使用例如Factory Method或Builder。
答案 3 :(得分:0)
好的,谢谢大家的帮助。
我接受了你的所有建议,我做了以下事情:
namespace Plugins
{
public class plugin1 : Iplugin
{
void doSomthing(string _str)
{
if (_str == "1")
{
// do somthing 1
}
}
}
public class plugin2 : Iplugin
{
void doSomthing(string _str)
{
if (_str == "2")
{
// do somthing 2
}
}
}
public class plugin3 : Iplugin
{
void doSomthing(string _str)
{
if (_str == "3")
{
// do somthing 3
}
}
}
}
这是所有插件的名称空间
现在在主应用程序中
namespace Factory
{
public interface Iplugin
{
void doSomthing(string _str);
}
class Program
{
static void Main(string[] args)
{
string @namespace = "Plugins";
var q = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.IsClass && t.Namespace == @namespace
select t;
q.ToList();
List<Iplugin> myList = new List<Iplugin>();
foreach (var item in q)
{
Iplugin temp=(Iplugin)Activator.CreateInstance(item);
myList.Add(temp);// a list with all my plugins
}
foreach (var item in myList)
{
item.doSomthing("string");
}
}
}
}