Jak nahrát pluginy v .NET?

hlasů
26

Rád bych, aby nějaký způsob tvorby dynamicky načítaných pluginy ve svém softwaru. Typický způsob, jak to udělat, je pomocí LoadLibrary funkce WinAPI načíst dll a volání GetProcAddress získat ukazatel na funkci uvnitř této dll.

Moje otázka je, jak mohu dynamicky načíst plugin v C # /. Net aplikace?

Položena 18/08/2008 v 06:34
zdroj uživatelem
V jiných jazycích...                            


8 odpovědí

hlasů
20

Následující fragment kódu (C #) konstruuje instanci jakýchkoli konkrétních tříd odvozených z Basenalezeno ve třídě knihovny (* DLL) v cestě aplikace a uloží je v seznamu.

using System.IO;
using System.Reflection;

List<Base> objects = new List<Base>();
DirectoryInfo dir = new DirectoryInfo(Application.StartupPath);

foreach (FileInfo file in dir.GetFiles("*.dll"))
{
    Assembly assembly = Assembly.LoadFrom(file.FullName);
    foreach (Type type in assembly.GetTypes())
    {
        if (type.IsSubclassOf(typeof(Base)) && type.IsAbstract == false)
        {
            Base b = type.InvokeMember(null,
                                       BindingFlags.CreateInstance,
                                       null, null, null) as Base;
            objects.Add(b);
        }
    }
}

Edit: Třídy na něž se odvolává Matt je asi lepší volba v .NET 3.5.

Odpovězeno 18/08/2008 v 06:41
zdroj uživatelem

hlasů
3

V podstatě, můžete to udělat dvěma způsoby.

Prvním z nich je importovat kernel32.dll a používání LoadLibrary a GetProcAddress, jak jste jej použít před:

[DllImport("kernel32.dll")]

internal static extern IntPtr LoadLibrary(String dllname);

[DllImport("kernel32.dll")]

internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);

Druhým důvodem je, aby to v .NET způsobem: pomocí odrazu. Zkontrolujte, zda System.Reflection názvů a následujícími způsoby:

První načtení sestavení by to cesta, pak se typ (třída) z ní, že je to jméno, pak dostanete metodu třídy tím, že je to jméno znovu a nakonec volání metody s příslušnými parametry.

Odpovězeno 18/08/2008 v 06:44
zdroj uživatelem

hlasů
28

Jak .NET 3.5 je tu byla přijata, pečený-in způsob, jak vytvořit a nahrát pluginy z aplikace .NET. Je to všechno v System.AddIn názvů. Pro více informací se můžete podívat na tento článek na webu MSDN: Doplňky a rozšiřitelnost

Odpovězeno 18/08/2008 v 07:07
zdroj uživatelem

hlasů
5

Jeden tip je načíst všechny pluginy a tak do vlastní AppDomain, protože kód běh může být potenciálně nebezpečný. Z vlastní AppDomain může být také použita k „filtr“ sestav a typů, které nechcete nahrát.

AppDomain domain = AppDomain.CreateDomain("tempDomain");

A načíst sestavení do domény aplikace:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath);
Assembly assembly = domain.Load(assemblyName);

Uvolnit aplikační domény:

AppDomain.Unload(domain);
Odpovězeno 18/08/2008 v 07:09
zdroj uživatelem

hlasů
2

Tento článek je trochu starší, ale stále použitelné pro vytvoření rozšiřitelnosti vrstvy ve vaší aplikaci:

Umožňují uživatelům přidávat Funkčnost .NET aplikací pomocí makra a Plug-Ins

Odpovězeno 18/08/2008 v 17:32
zdroj uživatelem

hlasů
4

Ano, ++ k Mattovi a System.AddIn (dvoudílný MSDN časopis článek o System.AddIn jsou k dispozici zde a zde ). Další technologie budete chtít prohlédnout, abyste získali představu, kde by mohl být .NET Framework chystá do budoucna je spravované rozšiřitelnost Framework v současné době k dispozici ve formě CTP na CodePlex.

Odpovězeno 09/09/2008 v 21:03
zdroj uživatelem

hlasů
8

Dynamicky Vkládání plug-inů

Informace o tom, jak dynamicky načíst sestavy .NET naleznete na tuto otázku (a mou odpověď ). Zde je kód pro nakládání vytváření AppDomaina vkládání sestavy do ní.

var domain = AppDomain.CreateDomain("NewDomainName");
var pathToDll = @"C:\myDll.dll"; 
var t = typeof(TypeIWantToLoad);
var runnable = domain.CreateInstanceFromAndUnwrap(pathToDll, t.FullName) 
    as IRunnable;
if (runnable == null) throw new Exception("broke");
runnable.Run();

Vykládání plug-inů

Typickým požadavkem rámce plugin je vyložit pluginy. Vyložit dynamicky namáhané shromáždění (např zásuvné moduly a doplňky), budete muset uvolnit jej obsahuje AppDomain. Pro více informací viz tento článek na webu MSDN na vykládání AppDomains .

pomocí WCF

Tam je přetečení zásobníku otázky a odpovědi , které popisují, jak pomocí Windows Communication Framework (WCF) k vytvoření rámce, plug-in.

Stávající Plug-In rámců

Vím, že ze dvou zásuvných rámcích:

Někteří lidé mluví o Managed rozšiřitelnost rámce (MEF) ve formě plug-in nebo add-in rámec, který to není. Více informací naleznete na této StackOverflow.com otázku a tuto StackOverflow.com otázku .

Odpovězeno 06/01/2013 v 16:56
zdroj uživatelem

hlasů
0

Tohle je moje implementace, inspirovaný v tomto kódu vyhnout k iteraci přes všechny sestavy a všech typů (nebo alespoň pro filtrování s LINQ). Jen jsem načíst knihovnu a pokusu o načtení třídu, která implemets společné sdílené rozhraní. Jednoduchá a rychlá :)

Jen deklarovat rozhraní v samostatné knihovně a odkazovat jej v obou váš systém a zásuvný modul:

public interface IYourInterface
{
    Task YourMethod();
}

Ve vašem pluginů knihovny, deklarovat třídy, která implementuje IYourInterface

public class YourClass: IYourInterface
{
    async Task IYourInterface.YourMethod()
    {
        //.....
    }
}

Ve vašem systému, prohlásit tuto metodu

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Linq;

public abstract class ReflectionTool<TSource> where TSource : class
{
    public static TSource LoadInstanceFromLibrary(string libraryPath)
    {
        TSource pluginclass = null;
        if (!System.IO.File.Exists(libraryPath))
            throw new Exception($"Library '{libraryPath}' not found");
        else
        {
            Assembly.LoadFrom(libraryPath);

            var fileName = System.IO.Path.GetFileName(libraryPath).Replace(".dll", "");
            var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(c => c.FullName.StartsWith(fileName));
            var type = assembly.GetTypes().FirstOrDefault(c => c.GetInterface(typeof(TSource).FullName) != null);

            try
            {
                pluginclass = Activator.CreateInstance(type) as TSource;
            }
            catch (Exception ex)
            {
                LogError("", ex);
                throw;
            }
        }

        return pluginclass;
    }
}

A to nazývají jako tímto způsobem:

IYourInterface instance = ReflectionTool<IYourInterface>.LoadInstanceFromLibrary("c:\pathToYourLibrary.dll");
Odpovězeno 03/01/2020 v 00:17
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more