Tag: plugins

如何读取DLL插件中的MEF元数据而不将整个DLL复制到内存中?

背景: 我有兴趣使用MEF在使用C#和.NET 4.0的WinForm应用程序中提供插件架构,但我不清楚几件事情。 第一:我还没有在C#中构建DLL的工作,我对DLL程序集的概念以及DLL如何正常加载到内存中有点模糊(意思是,所有一次或根据需要一块一块) 意图: 该程序将是一个机器硬件控制框架,将由一个主要的WinForm GUI组成,这是一个具有基本工具栏,菜单等的通用环境 – 但没有批量GUI内容。 (想想:MDI Parent,但实际上并非如此)。 插件提供特定机器的所有控件。 许多可能的插件中的每一个都可能包含30到50个大型UserControl,每个用户控件都包含许多WinForm控件和大量支持代码,构成了各种机器控制面板。 这意味着主程序是一个轻量级的通用框架,插件包含将在主程序用户界面中显示的大量GUI控件和function,包括许多图标,图像和其他资源。 这将使插件DLL可能非常大。 目标是允许用户从菜单中选择一个插件,然后在选择时加载并运行插件,然后插件将大部分空的主GUI填充面板,菜单和工具箱。 为此,我需要首先从每个插件中提取元数据以填充程序的初始菜单,其中包括插件标题,描述,图标,版本号和其他信息位。 以下是问题: 使用MEF,如果我尝试从存储在插件文件夹中的每个大型DLL中读取元数据,是否会在访问元数据值之前将整个DLL复制到内存中? 如果是这样,有没有办法打开每个DLL文件,只读取元数据到内存中构建初始菜单 – 然后通过MEF加载完整选定的DLL? 我假设用于通过MEF读取插件的典型DirectoryCatalog和AggregateCatalog模板将所有发现的DLL复制到内存中并将它们存储在目录集合中。 DLL是否包含一个连续的代码块(程序集),或者它们是否可以包含多个单独的块,这些块根据需要单独索引并复制到内存中(多个程序集)? 我可能不了解基本面,也许可能会混淆条款。 我将非常感谢对MEF,DLL和程序集的加载行为的任何了解。 谢谢 !

将MEF与C#一起使用,如何从插件中调用主机上的方法?

我正在尝试使用Managed Extensibility Framework(MEF)框架向我的C#应用​​程序添加插件可扩展性,到目前为止它还可以; 我有我的主/主机应用程序从定义的文件夹加载插件,并可以从主应用程序调用他们的方法等。 宿主应用程序和插件都引用了一个单独的dll程序集,其中包含所有项目通用的接口。 这工作正常,我可以调用/与主应用程序的插件交互。 但是,我也希望能够从插件中与宿主应用程序进行交互,但似乎无法了解这是如何完成的。 我希望能够从我的插件中获取/设置/执行主应用程序中的导出属性和方法。 目前我只能从主应用程序“发言”到插件,而不是相反。 我的代码到目前为止: 接口DLL namespace MefContracts { [InheritedExport] public interface IPlugin { String DoWork(); } public class Class1 { public IPlugin plugin { get; set; } } } 主要/主机应用程序 namespace MyMEF { class clsMEF { private CompositionContainer _container; [Import(typeof(MefContracts.IPlugin))] public MefContracts.IPlugin plugin; public clsMEF() { Compose(); } void […]

CreateInstanceAndUnwrap和Domain

我有一个属性,其实例我想在其他域中。 public ModuleLoader Loader { get { if(_loader == null) _loader = (ModuleLoader)myDomain.CreateInstanceAndUnwrap( this.GetType().Assembly.FullName, “ModuleLoader”, false, System.Reflection.BindingFlags.CreateInstance, null, null, null, null); System.Diagnostics.Debug.WriteLine(“Is proxy={0}”, RemotingServices.IsTransparentProxy(_loader)); //writes false _loader.Session = this; return _loader; } } 这很好用。 但我假设_loader实例上的所有方法调用都将在其他域(myDomain)中调用。 但是当我运行以下代码时,它仍然会编写主应用程序域。 public void LoadModule(string moduleAssembly) { System.Diagnostics.Debug.WriteLine(“Is proxy={0}”, RemotingServices.IsTransparentProxy(this)); System.Diagnostics.Debug.WriteLine( AppDomain.CurrentDomain.FriendlyName); System.Diagnostics.Debug.WriteLine(“———–“); } 是因为Unwrap()? 我在哪里做错了? 我知道AppDomain会创建单独的内存。 我需要的是我的主应用程序运行,它在不同的AppDomain中加载模块。 由于主应用程序还希望观看模块的一些活动以及与在单独域中运行的对象进行交互,因此实现它的最佳方法是什么。

appDomain.Unload(domain)后如何删除pluginassembly

我有一个奇怪的问题。 我想删除已加载的程序集(硬盘上的plugin.dll),但程序集被操作系统(vista)锁定,即使我已卸载它。 FE AppDomainSetup setup = new AppDomainSetup(); setup.ShadowCopyFiles = “true”; AppDomain appDomain = AppDomain.CreateDomain(assemblyName + “_AppDomain”, AppDomain.CurrentDomain.Evidence, setup); IPlugin plugin = (IPlugin)appDomain.CreateInstanceFromAndUnwrap(assemblyName, “Plugin.MyPlugins”); 我还需要assemblyinfos,因为我不知道pluginassembly中的哪些类实现了IPlugin接口。 在一个Pluginassembly中应该可以有多个插件。 Assembly assembly = appDomain.Load(assemblyName); if (assembly != null) { Type[] assemblyTypes = assembly.GetTypes(); foreach (Type assemblyTyp in assemblyTypes) { if (typeof(IPlugin).IsAssignableFrom(assemblyTyp)) { IPlugin plugin = (IPlugin)Activator.CreateInstance(assemblyTyp); plugin.AssemblyName = assemblyNameWithEx; […]

当控制器类在不同的程序集中时,如何将Controller注册到ASP.NET MVC中?

我的目标是修改asp.net mvc的控制器注册表,以便我可以在单独的(子)程序集中创建控制器和视图,只需将View文件和DLL复制到主机MVC应用程序,新控制器就可以“插入” “到主机应用程序。 显然,我需要某种IoC模式,但我不知所措。 我的想法是引用一个带有system.web.mvc的子程序集,然后开始构建从Controllerinheritance的控制器类: 单独组装: using System.Web; using System.Web.Mvc; namespace ChildApp { public class ChildController : Controller { ActionResult Index() { return View(); } } } 耶和华都很好。 但后来我考虑修改主机应用程序的Controller注册表以在运行时加载我的新子控制器,我感到困惑。 也许是因为我需要更深入地了解C#。 无论如何,我以为我需要创建一个CustomControllerFactory类。 所以我开始编写一个覆盖GetControllerInstance()方法的类。 在我打字时,intellisence突然出现: 主机MVC应用程序: public class CustomControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { return base.GetControllerInstance(requestContext, controllerType); } } 现在,在这一点上,我很茫然。 我不知道那是做什么的。 […]

带有C#插件的系统

我必须开发一个监控传感器信息的系统,但将来可能会添加许多传感器。 也就是说,我们的想法是开发一个由应用程序框架组成的系统。 传感器(因为它们中的每一个都具有通信和数据呈现特性)将作为插件添加到系统中。 我如何在C#上编码? 这是组件驱动开发的情况吗? 我应该使用动态库吗?

如何确定DLL是托管程序集还是本机(防止加载本机DLL)?

原标题:如何防止从.NET应用程序加载本机dll? 背景: 我的C#应用​​程序包括一个插件框架和通用插件加载器。 插件加载器枚举应用程序目录以识别插件dll(实质上它此时搜索* .dll)。 在同一个应用程序目录中是一个本机(Windows,非.NET)dll,间接地,其中一个插件dll依赖于它。 插件加载器盲目地假设native.dll是.NET程序集dll,只是因为它只检查文件扩展名。 当它尝试加载本机dll时,抛出exception: “无法加载文件或程序集’native.dll’或其依赖项之一。模块应该包含程序集清单。” 如果插件加载失败,我基本上创建了一个诊断报告,所以我试图避免让这个日志填满关于无法加载本机dll的消息(我甚至不想尝试)。 问题是: 是否有一些.NET API调用,我可以用来确定二进制文件是否恰好是.NET程序集,以便我不会尝试加载本机DLL? 也许从长远来看,我会将我的插件移动到一个子目录,但是现在,我只想要一个解决方案,不涉及在我的插件加载器中硬编码“native.dll”名称。 我想我正在寻找某种静态的Assembly.IsManaged()API调用,我忽略了……大概没有这样的API存在?

获取VS Add-in或DXCore插件的解决方案/项目文件列表

我正在尝试为Visual Studio编写一个加载项,除其他外,需要跟踪Visual Studio解决方案中的每个文件。 我知道我需要订阅什么事件(当打开解决方案时,在其中添加/删除/编辑文件时,项目中的文件相同等),但我不明白如何实际获取文件列表从任何一个。 我最近安装了CodeRush并且一直在使用DXCore框架。 我很高兴它的插件方法,但我仍然没有看到一个明显的方法来获得解决方案中的文件列表。 总结一下: 如何通过Visual Studio SDK 或 DXCore获得解决方案及其项目中可靠的文件列表?

C#插件架构,接口在插件之间共享

我把我的问题分成了一个简短的长版本,适合那些没有时间的人。 精简版: 我需要一些带有提供者和消费者插件的系统架构。 提供商应实施interface IProvider,消费者应实施IConsumer。 执行的应用程序应该只知道IProvider和IConsumer。 消费者实现可以向执行程序集(通过ServiceProcessor)询问哪些提供程序实现InterfaceX并获取List。 这些IProvider对象应该被转换为InterfaceX(在使用者中),以便能够将使用者挂钩到InterfaceX定义的某些事件上。 这将失败,因为执行程序集以某种方式不知道此InterfaceX类型(强制转换失败)。 解决方案是将InterfaceX包含在插件和执行程序集引用的某个程序集中,但这应该意味着对每个新的提供者/消费者对进行重新编译并且非常不受欢迎。 有什么建议? 长版: 我正在开发某种通用服务,它将使用插件来实现更高级别的可重用性。 该服务包含使用提供者和使用者的某种Observer模式实现。 提供者和使用者都应该是主应用程序的插件。 让我首先通过列出我在解决方案中的项目来解释服务是如何工作的。 项目A:用于托管所有插件和基本function的Windows服务项目。 TestGUI Windows窗体项目用于更轻松的调试。 来自Project B的ServiceProcessor类的一个实例正在执行与插件相关的东西。 此项目的子文件夹“Consumers”和“Providers”包含子文件夹,其中每个子文件夹分别包含一个使用者或提供者插件。 项目B:包含ServiceProcessor类的类库(在插件之间执行所有插件加载和调度等),IConsumer和IProvider。 项目C:链接到项目B的类库,由TestConsumer(实现IConsumer)和TestProvider(实现IProvider)组成。 TestProvider实现了一个额外的接口(ITest,它本身派生自IProvider)。 这里的目标是Consumer插件可以向ServiceProcessor询问它所拥有的提供者(至少实现IProvider)。 返回的IProvider对象应该被转换为它在IConsumer实现中实现的其他接口(ITest),以便使用者可以将事件处理程序挂钩到ITest事件。 项目A启动时,将加载包含使用者和提供者插件的子文件夹。 以下是我到目前为止遇到的一些问题并试图解决。 ITest过去常常驻留在Project C中,因为这仅适用于TestProvider和TestConsumer所知道的方法和事件。 一般的想法是保持项目A简单并且不知道插件彼此做什么。 使用项目C中的ITest和TestConsumer的Initialize方法中的代码将IProvider转换为ITest(当实现ITest的对象被称为IConsumer对象时,这不会在单个类库中失败)会发生无效的转换错误。 通过将ITest接口放入项目A引用的项目B中,可以解决此错误。 这是非常不受欢迎的,因为我们需要在构建新接口时重新编译项目A. 我试图将ITest放在由项目C引用的单个类库中,因为只有提供者和使用者需要知道这个接口,但没有成功:当加载插件时,CLR声明无法找到引用的项目。 这可以通过挂钩当前AppDomain的AssemblyResolve事件来解决,但不知何故这似乎也是不需要的。 ITest再次回到了B项目。 我尝试将项目C拆分为消费者和提供者的单独项目,并且都加载本身运行良好的程序集:两个程序集都驻留在Assemblies集合中或当前的AppDomain:Assembly found:Datamex.Projects.Polaris.Testing.Providers ,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = 2813de212e2efcd3发现大会:Datamex.Projects.Polaris.Testing.Consumers,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = ea5901de8cdcb258 由于消费者使用提供者,因此从消费者到提供者进行了引用。 现在AssemblyResolve事件再次触发,表明它需要以下文件:AssemblyName […]