Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[C#]Dynamisch instantieren van class uit Assembly

Pagina: 1
Acties:
  • 119 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
In mijn zoektocht om een systeem te maken waarbij ik plugins kan gebruiken, had ik het volgende bedacht:

Ik heb een directory met .NET assemblies. Deze bevatten een class, die een bepaalde interface implementeerd.

De interface ziet er als volgt uit:

C#:
1
2
3
4
5
6
7
8
9
10
11
using System;
using System.Collections.Generic;
using System.Text;

namespace PimsMonitor
{
    interface IMonitorPlugin
    {
        string Action();
    }
}


De class van de plugin ziet er als volgt uit:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;
using System.Collections.Generic;
using System.Text;

namespace PimsMonitor
{
    public class Plugin : IMonitorPlugin
    {
        public string Action()
        {
            return "Hello World! From TestPlugin!";
        }
    }
}


Wat ik nu wil is vanuit mijn applicatie, dynamisch de plugin assembly inladen, en deze casten naar de IMonitorPlugin interface.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace PimsMonitor
{
    class Plugin
    {
        Assembly PluginAssembly;
        IMonitorPlugin PluginObject;

        string Description;

        public Plugin(string FilePath)
        {
            PluginAssembly = Assembly.LoadFrom(FilePath);
            CreateInstance();
        }

        public void CreateInstance()
        {
            PluginObject = (IMonitorPlugin)PluginAssembly.CreateInstance("PimsMonitor.Plugin");
        } 
    }
}


Dit werkt niet. Ik krijg een InvalidCastException als ik de Instance wil casten naar IMonitorPlugin. Ik heb al heel wat met Reflection rond zitten spelen, maar krijg het niet voor elkaar.

Dus zowel aan de plugin kant, als aan de applicatiekant zijn de IMonitorPlugin interfaces hetzelfde.

Maak ik hier een enorme denkfout?

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 28-11 16:59
Het Type uit de assembly halen, en dan aan de Activator vragen om een instantie?

Let er wel op dat de Interface IMonitorPlugin voor beiden uit dezelfde assembly moet komen. Je kan bijvoorbeeld de hosting assembly referencen in je plugin.

[ Voor 50% gewijzigd door Xiphalon op 06-11-2007 15:50 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-11 22:54
Heb je al eens gekeken wat CreateInstance returned ?
Maw, heb je al eens je code gedebugged ? Waarschijnlijk returned CreateInstance NULL omdat hij de class die je specifieert niet kan vinden.

https://fgheysels.github.io/


Verwijderd

Topicstarter
darkmage schreef op dinsdag 06 november 2007 @ 15:48:
Het Type uit de assembly halen, en dan aan de Activator vragen om een instantie?

Let er wel op dat de Interface IMonitorPlugin voor beiden uit dezelfde assembly moet komen. Je kan bijvoorbeeld de hosting assembly referencen in je plugin.
Kan je hier een klein voorbeeld van geven?

Kom ik dan niet met versieverschillen te ziten?

  • Tepel
  • Registratie: Juni 2006
  • Laatst online: 17-08-2024
Ik hoop dat de code die je in dit voorbeeld hebt staan niet de code is die je gebruikt. Voor zover ik mij weet te herinneren vindt C# het niet lief als je twee classes met dezelfde naam aanmaakt in dezelfde namespace.

C#:
1
2
3
4
5
6
7
8
9
10
11
// <snip>
namespace PimsMonitor
{
    public class Plugin : IMonitorPlugin 
// </snip>

// <snip>
namespace PimsMonitor
{
    class Plugin 
// </snip>


Ik zelf heb dit soort van praktijken ook wel gedaan, even zoeken, ah hier
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
private void AddPlugin(string FileName)
{
    //Create a new assembly from the plugin file we're adding..
    Assembly pluginAssembly = Assembly.LoadFrom(FileName);
    
    //Next we'll loop through all the Types found in the assembly
    foreach (Type pluginType in pluginAssembly.GetTypes())
    {
        if (pluginType.IsPublic) //Only look at public types
        {
            if (!pluginType.IsAbstract)  //Only look at non-abstract types
            {
                //Gets a type object of the interface we need the plugins to match
                Type typeInterface = pluginType.GetInterface("PluginInterface.IPlugin", true);
                
                //Make sure the interface we want to use actually exists
                if (typeInterface != null)
                {
                    //Create a new available plugin since the type implements the IPlugin interface
                    Types.AvailablePlugin newPlugin = new Types.AvailablePlugin();
                    
                    //Set the filename where we found it
                    newPlugin.AssemblyPath = FileName;
                    
                    //Create a new instance and store the instance in the collection for later use
                    //We could change this later on to not load an instance.. we have 2 options
                    //1- Make one instance, and use it whenever we need it.. it's always there
                    //2- Don't make an instance, and instead make an instance whenever we use it, then close it
                    //For now we'll just make an instance of all the plugins
                    newPlugin.Instance = (IPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
                    
                    //Set the Plugin's host to this class which inherited IPluginHost
                    newPlugin.Instance.API = Global.PluginAPI;
                    
                
                    //NOTE: Dit moet pas gebeuren als de plugin geselecteerd wordt.
                    //Set the database connection to the plugin;
                    //newPlugin.Instance.dbCon = Global.dbCon;
                    

                    //Call the initialization sub of the plugin
                    newPlugin.Instance.Initialize();
                    
                    //Add the new plugin to our collection here
                    this.colAvailablePlugins.Add(newPlugin);
                    
                    //cleanup a bit
                    newPlugin = null;
                }   
                
                typeInterface = null; //Mr. Clean           
            }               
        }           
    }
    
    pluginAssembly = null; //more cleanup
}

[ Voor 73% gewijzigd door Tepel op 06-11-2007 16:07 ]

0x7F


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Tepel schreef op dinsdag 06 november 2007 @ 16:01:
[...]

Ik zelf heb dit soort van praktijken ook wel gedaan, even zoeken, ah hier
C#:
1
   ...
Paar opmerkingen:
[list]
• Het zelf op null zetten van variabelen aan het einde van de scope stamt uit het VB tijdperk en wordt vaak afgeraden omdat het nutteloos is en misschien zelfs een negatief effect op je GC;
• De IsPublic en IsAbstract kan je natuurlijk in 1 if-statement doen;
• Is dit pluginAssembly.GetType(pluginType.ToString()) niet een hele omslachtige manier om pluginType weer op te halen? (Lijkt me zo hoor, niet geprobeerd).

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

[quote]riezebosch schreef op dinsdag 06 november 2007 @ 16:23:
• Het zelf op null zetten van variabelen aan het einde van de scope stamt uit het VB tijdperk en wordt vaak afgeraden omdat het nutteloos is en misschien zelfs een negatief effect op je GC;
Waarom zou dat misschien een negatief effect hebben op de GC :?. Vziw hangt er geen extra semantiek aan het op null zetten van een variabele.

[ Voor 9% gewijzigd door .oisyn op 06-11-2007 16:26 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
.oisyn schreef op dinsdag 06 november 2007 @ 16:24:
[...]

Waarom zou dat misschien een negatief effect hebben op de GC :?. Vziw hangt er geen extra semantiek aan het op null zetten van een variabele.
Het idee is in elk geval dat de runtime zelf (door statische analyse) al ziet dat je de variabele niet meer gebruikt en hem opruimt. Ik weet het fijne niet ervan, maar er wordt gesuggereerd dat wanneer je aan het eind van je functie zelf de variabele nog op null de runtime dit niet meer kan zien, wat met name een een probleem kan vormen als je tussendoor nog een long-running-call doet.

Wat discussies:
ASP.NET: Garbage Collection implementation - Setting a object to null
ASP.NET: Assigning object to null in finally block is good or its just a performance problem
MSDN Forum: Best practice while writing C# functions

Ok, uiteindelijk ook een guideline gevonden:
Chapter 5 — Improving Managed Code Performance
Do not set local variables to null (C#) or Nothing (Visual Basic .NET) because the JIT compiler can statically determine that the variable is no longer referenced and there is no need to explicitly set it to null.
In hetzelfde stuk staat dan wel weer dat je lokale members of static variabelen wél op null moet zetten voor een long-running call als je ze niet meer nodig hebt, maar da's natuurlijk ook logisch omdat die niet opgeruimd zullen worden.

[ Voor 49% gewijzigd door riezebosch op 06-11-2007 16:54 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
No need is natuurlijk heel wat anders als "het mag niet" ;) Daarnaast zie ik niet in waarom een variabele niet meer door de GC gezien zou worden als deze Null is. Pas op het moment dat 'ie out-of-scope gaat is 'ie interessant voor de GC en of 'ie dan null is of niet boeit niet.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
RobIII schreef op dinsdag 06 november 2007 @ 16:54:
[...]

No need is natuurlijk heel wat anders als "het mag niet" ;) Daarnaast zie ik niet in waarom een variabele niet meer door de GC gezien zou worden als deze Null is. Pas op het moment dat 'ie out-of-scope gaat is 'ie interessant voor de GC en of 'ie dan null is of niet boeit niet.
Het lijkt erop dat de JIT een object markeert als collectable zodra hij niet meer gereferenced wordt door code. Dat hoeft niet het moment van out of scope gaan te zijn. Dat betekent dat voor het out-of-scope gaan de GC het object al kan opruimen. Ik leid dit af uit de links die geleverd zijn. Dit betekent dus dat het theoretisch efficienter is om niet vlak voor het moment van out-of-scope gaan een variabele op null te zetten. Nu kan ik mij zo voorstellen dat de JIT slim genoeg is om het op null zetten van een variabele niet van invloed te laten zijn op het al dan niet collectable zijn van een object, maar daar weet ik verder niks van.

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
RobIII schreef op dinsdag 06 november 2007 @ 16:54:
[...]

No need is natuurlijk heel wat anders als "het mag niet" ;) Daarnaast zie ik niet in waarom een variabele niet meer door de GC gezien zou worden als deze Null is. Pas op het moment dat 'ie out-of-scope gaat is 'ie interessant voor de GC en of 'ie dan null is of niet boeit niet.
Ik heb ook nergens gezegd dat het "niet mag", enkel dat het "afgeraden wordt" ;) Verder zoals bigbeng het idd ook verwoordt.

Edit, quote van dezelfde reference:
C#:
1
2
3
4
5
6
7
void func(&#8230;)
{
  String str1;
  str1="abc";
  // Avoid this   <---
  str1=null;
}


:P

[ Voor 12% gewijzigd door riezebosch op 06-11-2007 17:09 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

bigbeng schreef op dinsdag 06 november 2007 @ 17:05:
Nu kan ik mij zo voorstellen dat de JIT slim genoeg is om het op null zetten van een variabele niet van invloed te laten zijn op het al dan niet collectable zijn van een object, maar daar weet ik verder niks van.
Sterker nog, het maakt hierbij niet uit of je 'm op null zet of een andere waarde geeft. Het gaat erom of de referentie zelf nog gebruikt wordt. Als je de variabele een andere waarde assignt wordt de referentie niet meer gebruikt, en kan hij dus voortijdig opgeruimd worden. Ik vind de redenatie dan ook nogal raar. Waarom wel de moeite doen om te detecteren of een variabele gebruikt wordt, maar niet de moeite doen om te detecteren of dat "gebruik" daadwerkelijk een read is op die variabele ipv een read of write in het algemeen.

[ Voor 18% gewijzigd door .oisyn op 06-11-2007 17:41 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 28-11 16:59
Het heeft iets te maken met dode variabelen en SSA (wikipedia) en de register spills die je dan krijgt.
Ik heb even een afterdinnerdipje in combinatie met een compleet andere compilervorm in mijn kop dus echte uitleg wordt even lastig.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 00:17
En dan durven ze nog te beweren dat een GC alles zo makkelijk maakt.
Gief delete statement plx, dan weet ik tenminste zeker dat en wanneer het ding wordt opgeruimd. ( Hadden ze natuurlijk al lang moeten doen ipv dat halfz* using ... )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Deterministic finalization is de bom :P

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 12:05
dit lijkt erg op het probleem dat ik ooit hier mee had :)

\[.NET] Assembly.LoadFrom en IPlugin cast = exception

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Dit werkt bij mij prima:
C#:
1
2
3
4
5
6
7
8
9
Assembly a = Assembly.LoadFile(@"<local path>");
foreach (Type t in a.GetTypes())
{
    if (typeof(IMyPlugin).IsAssignableFrom(t))
    {
        IMyPlugin plugin = (IMyPlugin)Activator.CreateInstance(t);
        plugin.Execute();
    }
}


Edit:
Heb "t.GetInterface("ConsoleApplication2.IMyPlugin") != null" vervangen door "typeof(IMyPlugin).IsAssignableFrom(t)".

[ Voor 43% gewijzigd door riezebosch op 07-11-2007 10:23 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • mOrPhie
  • Registratie: September 2000
  • Laatst online: 21-11 07:55

mOrPhie

❤️❤️❤️❤️🤍

Wat riezebosch doet met IsAssignableFrom is niet alleen beter, maar de enige oplossing imho. Het kan heel goed zijn dat als je een dynamisch plugin systeem maakt (wat trouwens wat security overwegingen met zich mee brengt), dat iemand een class in een assembly probeert te laden die heel die interface niet implementeert.

Een experimentele community-site: https://technobabblenerdtalk.nl/. DM voor invite code.


  • 4of9
  • Registratie: Maart 2000
  • Laatst online: 13-12-2024
je class is niet public.

hmm ik zie dat je 2 classen Plugin hebt binnen dezelfde namespace.

[ Voor 59% gewijzigd door 4of9 op 07-11-2007 16:16 ]

Aspirant Got Pappa Lid | De toekomst is niet meer wat het geweest is...


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-11 22:54
Als ik de code zie in de topicstart, zou de class die TS wil instantieren, wel public zijn...

https://fgheysels.github.io/


  • 4of9
  • Registratie: Maart 2000
  • Laatst online: 13-12-2024
in het 2 code voorbeeld is eenzelfde classe die niet public is.

2 klassen binnen de zelfde namespace met dezelfde naam.

Ik heb namelijk een zelfde contructie gebruikt voor mijn plugin model en dat werkt als een zonnetje.

[ Voor 56% gewijzigd door 4of9 op 07-11-2007 16:18 ]

Aspirant Got Pappa Lid | De toekomst is niet meer wat het geweest is...

Pagina: 1