c# – 如何在使用MEF的插件DLL的元数据中包含图像?

c# – 如何在使用MEF的插件DLL的元数据中包含图像?,第1张

概述C#.NET 4.0 WinForms 我开始实现this tutorial中的MEF示例代码,该代码描述了为元数据创建自定义ExportAttribute属性.在我尝试在元数据中包含资源文件中的图像之前,一切都在顺利进行.目标是将每个插件DLL的标题,描述和图标提取为元数据,以便在主程序中构建插件菜单. 我现在得到编译错误: “An attribute argument must be a co C#.NET 4.0 WinForms

我开始实现this tutorial中的MEF示例代码,该代码描述了为元数据创建自定义ExportAttribute属性.在我尝试在元数据中包含资源文件中的图像之前,一切都在顺利进行.目标是将每个插件DLL的标题,描述和图标提取为元数据,以便在主程序中构建插件菜单.

我现在得到编译错误:

“An attribute argument must be a constant Expression,typeof Expression
or array creation Expression of an attribute parameter type”

所以现在我有一个问题,需要弄清楚:

1)如何在属性中包含图像?

要么

2)如何在不使用属性的情况下在MEF中包含元数据?

这是我正在使用的代码:

在合同类中:

// Metadata contract interfacepublic interface IPlugInMetadata{    string PlugInTitle { get; }    string PlugInDescription { get; }    Image PlugInIcon { get; }}// Plug-In contract interfacepublic interface IPlugIn{    voID StartPlugIn(object systemObject);    voID StopPlugin();}

插件DLL中的自定义属性:

[MetadataAttribute][AttributeUsage(AttributeTargets.Class,AllowMultiple = false)]public class PluginMetadataAttribute : ExportAttribute{    public string Title { get; set; }    public string description { get; set; }    public Image icon { get; set; }    public PluginMetadataAttribute(string plugInTitle,string plugInDescription,Image plugInIcon)         : base(typeof(IPlugInMetadata))    {        Title = plugInTitle;        description = plugInDescription;        icon = plugInIcon;    }}

最后,Plug-In DLL中的Program类:

[Export(typeof(IPlugIn))][PluginMetadata(Resourcefile.PlugInTitle,Resourcefile.PlugInDescription,Resourcefile.PlugInIcon24)]public class Program : IPlugIn{    public voID StartPlugIn(object systemObject)    {        Console.Writeline("Start Plug-In: " + Resourcefile.PlugInTitle);    }    public voID StopPlugin()    {        Console.Writeline("Stop Plug-In: " + Resourcefile.PlugInTitle);    }}

这条线产生错误.

[PluginMetadata(Resourcefile.PlugInTitle,Resourcefile.PlugInIcon24)]

显然,Resourcefile不被视为常量,但是我如何将图像用作元数据,或者这是不可能的? (请注意,图像设置为“嵌入.resx”)

感谢您的任何帮助或建议!

解决方法 找到了解决方案:

好的,据我所知,你不能在MEF元数据中使用图像或图标.但是,您可以为DLL文件指定一个图标,就像为EXE文件一样.然后可以使用.NET类型中内置的静态方法读取图标:

Icon MyDLlicon = Icon.ExtractAssociatedIcon(DLLfilePath);

我仍然不确定为什么你可以将资源文件中的字符串作为MEF元数据返回,而不是嵌入的图标或图像.

由于我一直试图拼凑一个功能性的示例程序,该程序现在提供带有图标的插件菜单几天,我想我会发布代码,以防它帮助其他任何人.

这是一个功能齐全的示例项目,具有以下功能:

>旨在成为包含5个项目的单一解决方案(MainProgram,ContractInterfaces,PlugInA,PlugInB,PlugInC)
> Post Build Events将自动将每个项目的DLL复制到一个常见的“Plug-Ins”文件夹中
> MainProgram(WinForm)项目将构建可用DLL插件的目录,并使用每个插件的图标和元数据标题填充ListVIEw
>双击ListVIEw项将实例化插件(利用Lazy实例化),然后启动它.
>每个插件将在启动时接收对主窗体的引用,创建一个新的TextBox,并将其发布到主窗体以证明它已运行并可以访问GUI.
>所选插件的标题,描述和版本元数据值将打印到控制台窗口

我为每个DLL分配了一个不同的Icon(来自旧的Visual Studio 6 Common Graphics Misc文件夹)

从DLL插件中提取图标以创建ListVIEw,并且一旦它们启动(在双击ListVIEw中的每个插件项之后),DLL就会创建文档框并将其发布到GUI.

将以下代码添加到名为“MainProgram”的全新C#WinForm项目中(我使用的是VS 2010):

由于某种原因,Code Sample解析器不喜欢Using语句,因此它们作为要点:

>使用系统;
>使用System.Collections.Generic;
>使用System.ComponentModel.Composition;
>使用System.ComponentModel.Composition.Hosting;
>使用System.Drawing;
>使用System.IO;
>使用System.windows.Forms;
>使用ContractInterfaces;
>(命名空间)MainProgram

public partial class Form1 : Form{    // Prerequisites to run:    //      1)  Project,Add Reference,Projects,ContractInterface    //      2)  Project,.NET,System.ComponentModel.Composition    [importMany(typeof(IPlugIn))]    private IEnumerable<Lazy<IPlugIn,IPlugInMetadata>> LoadedplugIns;    List<PlugInInfo> AvailablePlugIns = null;    public Form1()    {        InitializeComponent();    }    private voID Form1_Load(object sender,EventArgs e)    {        // Get a List of the available Plug-Ins        AvailablePlugIns = GetPlugInList();        // Prepare an ImageList to hold the DLL icons        ImageList imgList = new ImageList();        imgList.colorDepth = colorDepth.Depth32Bit;        imgList.ImageSize = new Size(32,32);        // Populate ImageList with Plug-In Icons        foreach (var item in AvailablePlugIns)        {            imgList.Images.Add(item.PlugInIcon.ToBitmap());        }        // Assign the ImageList to the ListVIEw        ListVIEw1.LargeImageList = imgList;        int imageIndex = 0;        // Create the ListVIEw items        foreach (var item in AvailablePlugIns)        {            ListVIEw1.Items.Add(item.PlugInTitle,imageIndex);            imageIndex++;        }        ListVIEw1.MouseDoubleClick += new MouseEventHandler(ListVIEw1_MouseDoubleClick);    }    voID ListVIEw1_MouseDoubleClick(object sender,MouseEventArgs e)    {        // Get the Plug-In index number         int plugInNum = ListVIEw1.SelectedItems[0].Index;        PlugInInfo selectedplugIn = AvailablePlugIns[plugInNum];        // Call the StartPlugIn method in the selected Plug-In.        // Lazy Instantiation will fully load the Assembly here        selectedplugIn.PlugIn.StartPlugIn(this);        Console.Writeline("Plug-In Title:          {0}",selectedplugIn.PlugInTitle);        Console.Writeline("Plug-In Description:    {0}",selectedplugIn.PlugInDescription);        Console.Writeline("Plug-In Version:        {0}",selectedplugIn.PlugInVersion);        Console.Writeline();    }    private List<PlugInInfo> GetPlugInList()    {        // Create a List to hold the info for each plug-in        List<PlugInInfo> plugInList = new List<PlugInInfo>();        // Set Plug-In folder path to same directory level as Solution        string plugInFolderPath = System.IO.Path.Combine(Application.StartupPath,@"..\..\..\Plug-Ins");        // Test if the Plug-In folder exists        if (!Directory.Exists(plugInFolderPath))        {            // Plug-In Folder is missing,so try to create it            try            { Directory.CreateDirectory(plugInFolderPath); }            catch            { MessageBox.Show("Failed to create Plug-In folder","Folder Creation Error:",MessageBoxbuttons.OK,MessageBoxIcon.Exclamation); }        }        try        {            // Create a catalog of plug-ins            var catalog = new DirectoryCatalog(plugInFolderPath,"*.dll");            AggregateCatalog plugInCatalog = new AggregateCatalog();            plugInCatalog.Catalogs.Add(catalog);            CompositionContainer container = new CompositionContainer(plugInCatalog);            // This line will fetch the Metadata from each plug-in and populate LoadedplugIns            container.ComposeParts(this);            // Save each Plug-Ins Metadata            foreach (var plugin in LoadedplugIns)            {                PlugInInfo info = new PlugInInfo();                info.PlugInTitle = plugin.Metadata.PlugInTitle;                info.PlugInDescription = plugin.Metadata.PlugInDescription;                info.PlugInVersion = plugin.Metadata.PlugInVersion;                info.PlugIn = plugin.Value;                plugInList.Add(info);            }            int index = 0;            // Extract icons from each Plug-In DLL and store in Plug-In List            foreach (var filePath in catalog.Loadedfiles)            {                plugInList[index].PlugInIcon = Icon.ExtractAssociatedIcon(filePath);                index++;            }        }        catch (fileNotFoundException fex)        {            Console.Writeline("file not found exception : " + fex.Message);        }        catch (CompositionException cex)        {            Console.Writeline("Composition exception : " + cex.Message);        }        catch (DirectoryNotFoundException dex)        {            Console.Writeline("Directory not found exception : " + dex.Message);        }        return plugInList;    }}public class PlugInInfo{    public string PlugInTitle { get; set; }    public string PlugInDescription { get; set; }    public string PlugInVersion { get; set; }    public Icon PlugInIcon { get; set; }    public IPlugIn PlugIn { get; set; }}

现在将一个名为“ListVIEw1”的ListVIEw控件添加到主窗体,并将其保存到窗体的右侧.插件中动态创建的TextBox将显示在左侧.

接下来添加一个名为“ContractInterfaces”的类项目,然后包含以下代码:

>使用System.windows.Forms;
>(namespace)ContractInterfaces

// Prerequisites to run://      1)  Project,"System.windows.Forms"public interface IPlugIn{    voID StartPlugIn(Form mainForm);}public interface IPlugInMetadata{    string PlugInTitle { get; }    string PlugInDescription { get; }    string PlugInVersion { get; }}

接下来添加一个名为“PlugInA”的类项目,然后包含以下代码:

>使用系统;
>使用System.ComponentModel.Composition;
>使用System.windows.Forms;
>使用ContractInterfaces;
>(名称空间)PlugInA

// Prerequisites to run://      1)  Project,"ContractInterface"//      2)  Project,"System.windows.Forms"//      3)  Project,"System.ComponentModel.Composition"//      4)  Project,PropertIEs,Build Events,Post-Build event command line://          xcopy "$(ProjectDir)$(OutDir)$(Targetfilename)"  "$(SolutionDir)Plug-Ins\" /Y//      5)  Project,Run the post-build event:,Always//      6)  Project,Application,Icon and manifest,[Select an icon][Export(typeof(IPlugIn))][PluginMetadata]public class Program : IPlugIn{    private Form MainForm;    public voID StartPlugIn(Form mainForm)    {        MainForm = mainForm;        // Place a TextBox on the Main Form        TextBox textBox = new TextBox();        textBox.Text = "PlugInA";        MainForm.Controls.Add(textBox);        textBox.WIDth = 65;        textBox.Height = 20;        textBox.top = 0;        textBox.left = 0;    }}// Create a custom strong-typed Metadata Attribute for MEF[MetadataAttribute][AttributeUsage(AttributeTargets.Class,AllowMultiple = false)]public class PluginMetadataAttribute : ExportAttribute{    public string PlugInTitle { get; set; }    public string PlugInDescription { get; set; }    public object PlugInVersion { get; set; }    public PluginMetadataAttribute()        : base(typeof(IPlugInMetadata))    {        PlugInTitle = "Plug-In A";        PlugInDescription = "This is Plug-In A";        PlugInVersion = "1.0.0.0";    }}

接下来添加一个名为“PlugInB”的类项目,然后包含以下代码:

>使用系统;
>使用System.ComponentModel.Composition;
>使用System.windows.Forms;
>使用ContractInterfaces;
>(名称空间)PlugInB

// Prerequisites to run://      1)  Project,[Select an icon][Export(typeof(IPlugIn))][PluginMetadata]public class Program : IPlugIn{    private Form MainForm;    public voID StartPlugIn(Form mainForm)    {        MainForm = mainForm;        // Place a TextBox on the Main Form        TextBox textBox = new TextBox();        textBox.Text = "PlugInB";        MainForm.Controls.Add(textBox);        textBox.WIDth = 65;        textBox.Height = 20;        textBox.top = 30;        textBox.left = 0;    }}// Create a custom strong-typed Metadata Attribute for MEF[MetadataAttribute][AttributeUsage(AttributeTargets.Class,AllowMultiple = false)]public class PluginMetadataAttribute : ExportAttribute{    public string PlugInTitle { get; set; }    public string PlugInDescription { get; set; }    public object PlugInVersion { get; set; }    public PluginMetadataAttribute()        : base(typeof(IPlugInMetadata))    {        PlugInTitle = "Plug-In B";        PlugInDescription = "This is Plug-In B";        PlugInVersion = "1.0.0.1";    }}

接下来添加一个名为“PlugInC”的类项目,然后包含以下代码:

>使用系统;
>使用System.ComponentModel.Composition;
>使用System.windows.Forms;
>使用ContractInterfaces;
>(命名空间)PlugInC

// Prerequisites to run://      1)  Project,[Select an icon][Export(typeof(IPlugIn))][PluginMetadata]public class Program : IPlugIn{    private Form MainForm;    public voID StartPlugIn(Form mainForm)    {        MainForm = mainForm;        // Place a TextBox on the Main Form        TextBox textBox = new TextBox();        textBox.Text = "PlugInC";        MainForm.Controls.Add(textBox);        textBox.WIDth = 65;        textBox.Height = 20;        textBox.top = 60;        textBox.left = 0;    }}// Create a custom strong-typed Metadata Attribute for MEF[MetadataAttribute][AttributeUsage(AttributeTargets.Class,AllowMultiple = false)]public class PluginMetadataAttribute : ExportAttribute{    public string PlugInTitle { get; set; }    public string PlugInDescription { get; set; }    public object PlugInVersion { get; set; }    public PluginMetadataAttribute()        : base(typeof(IPlugInMetadata))    {        PlugInTitle = "Plug-In C";        PlugInDescription = "This is Plug-In C";        PlugInVersion = "1.0.0.2";    }}

解决方案应如下所示:

右键单击Solution,然后选择“Project DependencIEs …”.设置依赖项如下:

> MainProgram – 取决于 – ContractInterface
> PlugInA – 取决于 – ContractInterface
> PlugInB – 取决于 – ContractInterface
> PlugInC – 取决于 – ContractInterface
> ContractInterface – 取决于 – [没有]

右键单击解决方案,然后选择“项目构建顺序…”.构建顺序应如下所示:

> ContractInterface
> PlugInA
> PlugInB
> PlugInC
> MainProgram

构建并运行该程序.您应该看到3个DLL文件被复制到与解决方案文件(* .sln)相同的目录级别的新“Plug-Ins”文件夹中.如果没有,请检查项目构建顺序,依赖项,以及您是否根据上面插件代码中的注释输入了构建后事件.如果文件在那里,则应在带有插件条目的表单中填充ListVIEw.双击每个ListVIEw条目以启动插件.

玩得开心,我希望这有助于某人….

总结

以上是内存溢出为你收集整理的c# – 如何在使用MEF的插件DLL的元数据中包含图像?全部内容,希望文章能够帮你解决c# – 如何在使用MEF的插件DLL的元数据中包含图像?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1252608.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存