Jag ska fixa ett sökprg med dll-plugins. Nedan är vad jag fått fram än så länge, men följande problem behöver hjälp med: Hej, du kan använda dig av MyAssembly.FullName, GetName() för att få ut all info om den assembly dy dynamiskt läser in. Dock ger den rätt mkt info: Okej... Oj... :-) Tänkte bara komma med en grej... vet inte hur du hade tänkt dig att du skulle göra men när man skriver plugins till en del program får ju själva instansen av huvudprogrammet när de laddas. öh? tja, hittade inget exempel med just interfaces men här kanske är nåt att utgå ifrån: Varför skulle inte detta vara ett bra sätt? Tycker det verkar fungera. Man skickar med huvudprogrammet ex sin form in i sin plugin som då kan nå formulärets publika metoder m.m. Fatta inte riktigt det där me onstart :P (är man tonåring så är man) Fatta inte riktigt det där me onstart :P (är man tonåring så är man) OnStart var bara en metod som man angett skall vara obligatorisk på sina plugins. Den utför saker när du startar din plugin. OnStart finns troligen med som krav i ett interface, ex Ok, har satt ihop ett litet exempel. "kanske man skulle kunna skriva en artikel om sånt här..." hehe.. jo, man ska ju ha tid oxå... får se, kanske blir lite tid över nu under jul Fint exempel, håller på att försöka fixa in det, men jag får ett fel när jag Lite dum fråga kanske, men hur får jag in pluginsen i en lista? Nu har jag fått till ett litet klurigt problem:DLL-plugins
- Hur fångar jag vad namespacet heter? Eller finns det nåt annat jag kan göra istället för MyType = MyAssembly.GetType("dynDLL.Class1");???
- Kan pluginen komma åt publika structs och metoder i huvudprg:et? Tänkte bla att ha en public string hämtaSida() och en public string hämtaSidaPOST()
- Hur kommer jag åt publika strängar i pluginen, Assembly.GetFields() eller?
<code>
System.Reflection.Assembly MyAssembly;
MyAssembly = Assembly.LoadFrom(@"d:\thomas mapp\mina dokument\visual studio projects\Exempel - Ladda dll dynamiskt - DLL\bin\release\dyndll.dll");
System.Type MyType;
MyType = MyAssembly.GetType("dynDLL.Class1");
System.Reflection.MethodInfo MyMethod;
MyMethod = MyType.GetMethod("Abs");
Object MyInstance;
MyInstance = Activator.CreateInstance(MyType);
MyMethod.Invoke(MyInstance, null); //new Object[] {-12}
</code>
- MrTSv: DLL-plugins
Ex:
Minstrel.Library.Data, Version=1.0.1000.27310, Culture=neutral, PublicKeyToken=n
ull
Ang komma åt huvudprogrammet från din plugin kan nog bli klurigt. Har inte testat att göra så själv,
men ev kan du skicka in form classen in till din plugin och på så vis justera saker för den. Går inte det så kanske du kan hämta de assemlies som ligger i din appdomän...
Det är svårt att ge svar då jag inte vet vad det är du vill komma åt, om det är programmets alla egenskaper eller bara en viss grej, ex textbox.
Denna kod hämtar alla Assemblies som ligger i din AppDomän. Kanske det kan vara något att gå på?
<code>
public static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
Evidence asEvidence = currentDomain.Evidence;
currentDomain.Load("CustomLibrary",asEvidence);
Assembly[] assems = currentDomain.GetAssemblies();
Console.WriteLine("List of assemblies loaded in current appdomain:");
foreach (Assembly assem in assems)
Console.WriteLine(assem.ToString());
}
</code>
Om du kör casting på med dig plugin så kommer du åt dess metoder som om du deklarerade den själv.
<code>
myInstance = (<typen>)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(<info>,<info>);
</code>
Om du skall ha in flera plugins beroende på olika val i din applikation så kan du implementera ett gemensamt interface för dem och på så vis nå en gemensam metod eller property. Annars måste du köra reflection och ta reda på hur classen ser ut.
Jag hoppas detta gav lite information.
Mvh JohanSv: DLL-plugins
Men hur man tag i en sträng/variabel/objekt i pluginen, tänkte tex ha string namn="Google",string hemsida="http://www.google.com" etc
hur menade du med?
<info>
Om du kör casting på med dig plugin så kommer du åt dess metoder som om du deklarerade den själv.
myInstance = (<typen>)AppDomain.CurrentDomain.CreateInstanceAndUnwrap(<info>,<info>);
</info>
Ska testa det andra imorrn när jag är lite piggare ;)
- MrTSv: DLL-plugins
Om du kör casting på med dig plugin så kommer du åt dess metoder som om du deklarerade den själv.
skall vara
Om du kör med casting på din plugin så kommer du åt dess metoder som om du deklarerade den själv.
Mvh JohanSv: DLL-plugins
Dvs du har en klass i din Plugin som implementerar ett Interface (säg IMyApp)
I den finns kanske två metoder
OnStart(MyApp owner);
OnClose();
Sen ser du bara till att din MyApp kallar på OnStart med sig själv som parameter när alla pluginsen laddas in och OnClose innan programmet stängs ner. Då kan du ju kontrollera vilka metoder som pluginen kan använda etc.
Hur man skall hitta rätt klass som implementerar interfacet vet i f-n men det borde ju gå... jag menar du är väl inte först i världen med att skriva en plugin ;-)
Lite tankar baraSv: DLL-plugins
skulle man kunna få ett exempel? Jag är inte så haj på interface o sånt..
Mr T @thomasa88.homeip.netSv: DLL-plugins
http://codeproject.com/csharp/extensibleui.asp
I det exemplet skulle man ju t.ex. kunna lägga till en metod i Plugin klassen som hette OnStart(Form frm)
Som du kallar på i AddPlugin enligt exemplet:
NewPlugin.OnStart(this);
Vet inte om det är detta du söker men det är så en del applikationer fungerar när man skriver plugins till dem iallafall. Vet inte om nån har nån länk om hur man egentligen bör göra sin arkitektur i såna här lägen. Sitter med ungefär samma grejer, att jag nån gång i framtiden vill kunna skriva plugins till mitt eget program...Sv: DLL-plugins
<code>
NewPlugin.OnStart(this);
</code>
Det som kan vara kul är väl mer registeringshantering av pluggar, så de dynamiskt går att slänga på eller av. Kanske en XML fil som hantererar pluggarna eller vad som..
Mvh JohanSv: DLL-plugins
Såg iaf att de hade en pluginlib i exemplet, det var ju en asbra ide :D
- net.MrTSv: DLL-plugins
Såg iaf att de hade en pluginlib i exemplet, det var ju en asbra ide :D
- net.MrT
Edit.
ajdå, servern svara inte så jag skicka igenSv: DLL-plugins
interface IPlugin
{
bool OnStart...
På så vis kan du starta vilket plugin som helst via ex en controller klass eller vad du nu vill bygga. Kanske det är din main metod som skall läsa in dina plugins och starta upp dem?
<code>
public static Main(.....)
{
<läs in plugins DLLerna dynamiskt från ex en pluginmapp....>
<starta alla plugins>
plugin1.OnStart(this);
plugin2.OnStart(this);
plugin3.OnStart(this);
}
</code>
OBS! Bara kladdkod, här kanske du skall köra en loop som skapar varje instans av dina pluggar och starta dem. Du kan strunta i OnStart och skapa en generell konstruktor om du vill oxå.. OnStart ger mer spårbarhet i koden och en mall hur andra ex kan bygga egna plugga och kasta in dem till din programvara.
Mvh Johan
</code>Sv: DLL-plugins
Det består egentligen utav tre assemblies.
Ett huvudprogram (en winexe)
Ett Interface classlibrary (Plugin)
En plugin classlibrary (MyPlugin)
Interfacet (Plugin.IPlugin)
<code>
using System;
using System.Windows.Forms;
namespace Plugin
{
public interface IPlugin
{
void OnStart(Form owner);
void Close();
}
}
</code>
Plugin som refererar till assemblyn Plugin
<code>
using System;
using System.Windows.Forms;
using Plugin;
namespace MyPlugin
{
/// <summary>
/// Summary description for Plugin.
/// </summary>
public class Plugin:IPlugin
{
public Plugin()
{
}
public void OnStart(Form frm)
{
MessageBox.Show(frm.Text);
}
public void Close()
{
MessageBox.Show("Close");
}
}
}
</code>
En WinExe där jag la en referens till Plugin oxå. Sedan bestämde jag att jag skulle ladda alla mina plugins från directoriet "Plugins" som skulle ligga i samma directory som min exe. Detta är huvudprogrammet:
<code>
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using Plugin;
namespace MyApp
{
/// <summary>
/// Summary description for MyForm.
/// </summary>
public class MyForm : System.Windows.Forms.Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public MyForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
CheckPlugins();
}
private void CheckPlugins()
{
string path=Path.Combine(Environment.CurrentDirectory,"Plugins"); //leta i directoriet "Plugins"
string[] files=Directory.GetFiles(path,"*.dll"); //kolla bara efter dll:er
for(int i=0;i<files.Length;i++)
{
LoadPlugin(files[i]);
}
}
private bool IsInterface(Type type, string interfacename)
{
Type itype=type.GetInterface(interfacename);
if(itype!=null)return true;
else return false;
}
private void LoadPlugin(string path)
{
Assembly asm=Assembly.LoadFrom(path);
Type[] types=asm.GetTypes();
for(int i=0;i<types.Length;i++)
{
if(types[i].IsClass && IsInterface(types[i],"Plugin.IPlugin")) //kolla om det är en klass och implementerar Plugin.IPlugin
{
object obj=asm.CreateInstance(types[i].FullName); //skapa en instans
if(obj!=null)
{
IPlugin plugin=(Plugin.IPlugin)obj;
plugin.OnStart(this);//anropa onstart OBS här vill man kanske spara sin plugin nånstans oxå, typ i en arraylist eller nåt
}
}
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.Size = new System.Drawing.Size(300,300);
this.Text = "MyForm";
}
#endregion
}
}
</code>
Så nånting skulle man ju kunna göra...
Hoppas det kan vara till nån hjälp... kanske man skulle kunna skriva en artikel om sånt här...Sv: DLL-plugins
Det tycker jag du kan göra, det är rätt få artiklar som kommer in, och många kommer nog tycka detta är intressant, tror du inte det? Sv: DLL-plugins
Sv: DLL-plugins
-----------------------------
Ajdå hade ingen reference till System.Windows.Forms :P Add...
Mr T @thomasa88.homeip.netSv: DLL-plugins
Jag skriver:
Plugin.IPlugin[] plgs;
men när jag försöker initera det med
plgs=new
ploppar inte IPlugin upp under Plugin, och Plugin kan man inte välja.. (kompilationsfel)
Edit.
Ok, jag fick in dem i en Arraylist, men hur får jag ut en sträng ur pluginen. Har försökt med
Edit.
Fick det att funka med
interface:
<code>
string name
{
get;
}
</code>
plugin-class
<code>
public string name
{
get
{
return "TestPlugin";
}
}
</code>
<info>
Finns det nåt enklare sätt, tex nåt me string name; i interfacet och i constructorn i pluginen name="TestPlugin";?
<info>
- MrTSv: DLL-plugins
Jag har i namespacet interfacet IPlugin, men nu har jag också en struct som heter hit. Det är tänkt att pluginen ska stoppa sina sökresultat där. Nu till problemet: hit ska kunna returnera en sträng med data genom en funktion kallad string getHit() som ska finnas i structen hit. Så långt är allt väl, men nu är det meningen att de olika pluginsen ska ha olika getHit(), eftersom de söker olika sidor. Hur fixar jag ihop det här nu?
Edit.
Kanske smartare att köra med olika variabler som får datan när hit:en skapas..?
- MrT