Laden...

Probleme mit Interfaces

Erstellt von -acid- vor 18 Jahren Letzter Beitrag vor 18 Jahren 2.736 Views
-
-acid- Themenstarter:in
885 Beiträge seit 2004
vor 18 Jahren
Probleme mit Interfaces

Hallo Leute,

ich bräuchte mal eure Hilfe. Und zwar habe ich drei Interfaces:

public interface IPlugin : IPlugin1, IPlugin2
{
}

public interface IPlugin1
{
  string Name {get;}
}

public interface IPlugin2
{
  string Wert {get;}
}

Auf diese Interfaces greife ich unterschiedlich in Dlls zu:

// DLL1
public class MyLib1 : IPlugin1 {}

//DLL2
public class MyLib2 : IPlugin2 {}

Diese DLLs werden in einer Hostdatei geladen:

Assembly pluginAssembly = Assembly.LoadFrom(MyPath);
...

Und jeweils eine Instanz erstellt:

Type typeInterface = pluginType.GetInterface("IPlugin", true);
(IPlugin)Activator.CreateInstance(...)

Jetzt zu meinem Problem:
Die DLLs sollen jeweils unterschiedliche Variablen beinhalten, dafür die verschiedenen Interfaces. Schlussendlich möchte ich aber durch den Cast erreichen, dass alle von einem Typ sind (IPlugin). Was mache ich falsch? Leider habe ich wenig Ahnung was dieses Thema angeht, aber ich würde gerne verstehen, wo mein Fehler liegt. Evtl. ist ja schon meine Vorgehensweise falsch.

P
939 Beiträge seit 2003
vor 18 Jahren

Hier ist der Fehler:

public interface IPlugin : IPlugin1, IPlugin2
{
}

public interface IPlugin1
{
  string Name {get;}
}

public interface IPlugin2
{
  string Wert {get;}
}

Da erbt IPlugin von IPlugin1 und IPlugin2.

Du möchtest es aber so haben:

public interface IPlugin
{
}

public interface IPlugin1 : IPlugin
{
  string Name {get;}
}

public interface IPlugin2 : IPlugin
{
  string Wert {get;}
}

Gruss
Pulpapex

-
-acid- Themenstarter:in
885 Beiträge seit 2004
vor 18 Jahren

Hey Pulpapex,

leider klappt es nicht so ganz. Das Problem ist, dass ich in der DLL immer von einer Art "BaseInterface" erben will sprich "IPlugin1". Also schreibe ich

class myClass : UserControl, IPlugin1

Das wiederspricht aber meiner Lademethode der DLLs

Type typeInterface = pluginType.GetInterface("IPlugin", true);
(IPlugin)Activator.CreateInstance(...)

da ja nur nach dem Interface "IPlugin" gesucht wird und das leer ist. Schreibe ich nun meine Standardwerte in das Interface "IPlugin" und in der DLL

class myClass : UserControl, IPlugin

habe ich zwar diese Standardwerte, kann jedoch später vom Host aus nicht auf Werte vom Interface "IPlugin2" zugreifen. Folge? Ich erbe auch von "IPlugin2", was aber wieder nicht geladen wird, wegen

 pluginType.GetInterface("IPlugin", true);

Wie mache ich das richtig?

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo -acid-,

also so ganz verstehe ich es immer noch nicht, aber so wie es verstanden habe, denke ich, dass Pulpapex schon den richtigen Tipp gegeben hat.

herbivore

-
-acid- Themenstarter:in
885 Beiträge seit 2004
vor 18 Jahren

Also nochmal etwas genauer:

Ich habe DLLs (Plugins) welche alle von UserControl erben und zusätzlich von einem Interface. Das Interface stellt Standardwerte, zum Beispiel "Name", zur Verfügung wovon die Plugins auch erben sollen, was also ergibt:

// DLL1
public class MyLib1 : UserControl, IPlugin {}

//DLL2
public class MyLib2 : UserControl, IPlugin {}

Analog dazu sieht mein Interface so aus:

public interface IPlugin
{
  string Name {get;}
}

Und es gibt ein Methode im Host, der die Plugins lädt bzw. eine Instance erstellt:

Assembly pluginAssembly = Assembly.LoadFrom(PluginPath);
foreach (Type pluginType in pluginAssembly.GetTypes())
{
  Type typeInterface = pluginType.GetInterface("IPlugin", true);
  if (typeInterface != null)
  {
     ... (IPlugin)Activator.CreateInstance(...);
     ...
  }
}

Somit kann ich also jetzt auf meine Instanz bzw. auf dessen Standardwerte zugreifen zb mit

plugin.Instance.Name

Jetzt zum Problem:
Ich möchte gerne noch zusätzliche Werte bereitstellen, die aber nicht alle Plugins haben sollen, sondern nur teilweise. Deswegen wollte ich ein zweites Interface erstellen. Num muss ich immer in den DLLs schreiben von welchem Interface geerbt werden soll und könnte da mit Kommas alle Interfaces reinschreiben. Das Problem dabei ist, dass mir aber nur durch meine Lademethode "IPlugin" ausgelesen und gecastet wird. Das heißt ich benötige dafür eine Lösung.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo -acid-,

sorry, aber jetzt wird es ganz konkus. Oben schreibst du


public interface IPlugin1
{
  string Name {get;}
}

und jetzt


public interface IPlugin
{
  string Name {get;}
}

Das macht es nicht gerade einfacher. Ich gehe mal von der ersten Version aus.

Jetzt mal im Allgemeinen: Wenn alle Klassen IPlugin1 implementieren und manche zusätzlich IPlugin2, dann ist es doch ganz normal, wenn du bei manchen Klassen IPlugin1 und bei manchen Klassen IPlugin1, IPlugin2 in die Liste schreibst. Da alle Klassen IPlugin1 implementieren, kannst du sie auch alle über IPlugin1 laden. Wenn du auf die Member zugreifen willst, die durch IPlugin2 implementiert sind, benutzt du einfach obj as IPlugin2 auf die schon geladenen Objekte. IPlugin brauchst du bei dieser Vorgehensweise gar nicht.

herbivore