Domanda

I have verybasic question ( i dont know why i unable to think stright ).

I am trying to do some polymorphism .

I have interface look like this:

Public interface Iplugin
{

   void doSomthing(string _str);
}

I also have some plugins classes that implament this interface

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

So I have the main class and I would like it to invoke the all plug in

BUT I would like it to save the OCP (Open-Closed Principle) so If I will add in the future another plugin class the main class will not changed.

This is the main class

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
  }
} 
È stato utile?

Soluzione 4

Ok Thank you all for your help.

I take all your advice and I did the following:

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


 }
}

SO this is name space with all the plugins

now in the main app

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

        }

    }
}

}

Altri suggerimenti

Of course, to create a specific Iplugin you need to know the implementing type. Look at the Factory Pattern.

For cases like this i like to use the Factory Pattern. You can easily combine that with some Attributes and Reflection magic to build a repository of available plugins

[PluginAttribute("myPlugin")]
class MyPlugin : IPlugin

now the factory initially checks all classes in all loaded assemblies and searches for the attribute and stores the type and the plugin string identifier in a dictionary.

class PluginFactory
{
    static Iplugin CreatePlugin(string aName)
    {
        return Activator.CreateInstance( sRegisteredPlugins[aName]);
    }

    private static Dictionary<string, Type> sRegisteredPlugins;
}

You could add a collection to store your plugins. The collection can be filled in one place, then passed to another method which just iterates through all plugins and invokes them. This way it is totally independent of what types of plugins there are in the collection.

And as @Ian mentioned, you need to declare doSomthing virtual for this to work properly.

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

This is a simplistic example of Dependency Injection, which is one well known application of polymorphism (well, to make it real DI, you should put func into a different class). To make your code more flexible, and to decouple the creation of your plugins from their usage, you can also use e.g. a Factory Method or Builder.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top