Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9233009
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 18, 20262026-06-18T06:27:00+00:00 2026-06-18T06:27:00+00:00

C# .NET 4.0 WinForms I started implementing MEF example code from this tutorial which

  • 0

C# .NET 4.0 WinForms

I started implementing MEF example code from this tutorial which describes creating a custom ExportAttribute Attribute for metadata. Everything was going swimmingly until I tried to include an image from a Resource File in the metadata. The goal being to extract the title, description, and icon for each plug-in DLL as metadata for constructing a menu of plug-ins in the main program.

I now get the compile error:

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

So now I have a problem, and need to figure out either:

1) How to include an image in a attribute ?

or

2) How to include metadata in MEF without using attributes ?

Here is the code that I am using:

In the contract class:

// Metadata contract interface
public interface IPlugInMetadata
{
    string PlugInTitle { get; }
    string PlugInDescription { get; }
    Image PlugInIcon { get; }
}

// Plug-In contract interface
public interface IPlugIn
{
    void StartPlugIn(object systemObject);
    void StopPlugin();
}

The custom attribute in the Plug-In 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;
    }
}

And finally, the Program class in the Plug-In DLL:

[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);
    }
}

This line is producing the error.

[PluginMetadata(ResourceFile.PlugInTitle, ResourceFile.PlugInDescription, ResourceFile.PlugInIcon24)]

Obviously the ResourceFile is not considered a constant, but then how can I use an image as metadata, or is that not possible ? ( Note that the image is set as “Embedded in .resx” )

Thanks for any help or suggestions !

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-18T06:27:01+00:00Added an answer on June 18, 2026 at 6:27 am

    Found a solution:

    OK, as far as I can tell, you cannot use images or icons in MEF metadata. You can however assign an icon to the DLL file, just as you can for EXE files. The icon can then be read using a static method built into the Icon type for .NET:

    Icon MyDLLIcon = Icon.ExtractAssociatedIcon(DLLFilePath);
    

    I am still not exactly sure why you can return strings from a Resource file as MEF metadata, but not embedded Icons or Images.

    Since I have been trying to piece together a functioning example program that provides a Plug-In menu with icons for a couple of days now, I figured that I would post the code in case it helps anyone else.


    This is a fully functional example project with the following features:

    • Intended to be a single Solution with 5 Projects ( MainProgram, ContractInterfaces, PlugInA, PlugInB, PlugInC )

    • Post Build Events will automatically copy the DLLs from each project to a common “Plug-Ins” folder

    • The MainProgram (WinForm) project will build a catalog of the available DLL Plug-Ins and populate a ListView with the Icons and metadata Title of each Plug-In

    • Double-Clicking the ListView item will instantiate the Plug-In ( leveraging Lazy instantiation ), and start it.

    • Each Plug-In will receive a reference to the main Form at start up, create a new TextBox, and post it to the main Form to prove that it ran and can access the GUI.

    • The Title, Description, and Version metadata values of the selected Plug-In will print to the Console Window


    I assigned a different Icon to each DLL ( from the old Visual Studio 6 Common Graphics Misc folder )

    Screenshot

    The icons were extracted from the DLL Plug-Ins to create the ListView, and the TextBoxes were created and posted by the DLLs to the GUI once they started ( after double-clicking each Plug-In item in the ListView ).


    Add the following code to a fresh new C# WinForm project called “MainProgram” ( I used VS 2010 ):

    For some reason the Code Sample parser is not liking the Using statements, so here they are as bullet points:

    • using System;
    • using System.Collections.Generic;
    • using System.ComponentModel.Composition;
    • using System.ComponentModel.Composition.Hosting;
    • using System.Drawing;
    • using System.IO;
    • using System.Windows.Forms;
    • using ContractInterfaces;
    • (namespace) MainProgram

    public partial class Form1 : Form
    {
        // Prerequisites to run:
        //      1)  Project, Add Reference, Projects, ContractInterface
        //      2)  Project, Add Reference, .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; }
    }
    

    Now add a ListView Control called “listView1” to the main Form, and keep it to the Right side of the Form. The dynamically created TextBoxes from the Plug-Ins will show on the left.


    Next add a Class Project called “ContractInterfaces”, then include this code:

    • using System.Windows.Forms;
    • (namespace) ContractInterfaces

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

    Next add a Class Project called “PlugInA”, then include this code:

    • using System;
    • using System.ComponentModel.Composition;
    • using System.Windows.Forms;
    • using ContractInterfaces;
    • (namespace) PlugInA

        // Prerequisites to run:
    //      1)  Project, Add Reference, Projects, "ContractInterface"
    //      2)  Project, Add Reference, .NET, "System.Windows.Forms"
    //      3)  Project, Add Reference, .NET, "System.ComponentModel.Composition"
    //      4)  Project, Properties, Build Events, Post-Build event command line:
    //          xcopy "$(ProjectDir)$(OutDir)$(TargetFileName)"  "$(SolutionDir)Plug-Ins\" /Y
    //      5)  Project, Properties, Build Events, Run the post-build event:, Always
    //      6)  Project, Properties, 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";
        }
    }
    

    Next add a Class Project called “PlugInB”, then include this code:

    • using System;
    • using System.ComponentModel.Composition;
    • using System.Windows.Forms;
    • using ContractInterfaces;
    • (namespace) PlugInB

    // Prerequisites to run:
    //      1)  Project, Add Reference, Projects, "ContractInterface"
    //      2)  Project, Add Reference, .NET, "System.Windows.Forms"
    //      3)  Project, Add Reference, .NET, "System.ComponentModel.Composition"
    //      4)  Project, Properties, Build Events, Post-Build event command line:
    //          xcopy "$(ProjectDir)$(OutDir)$(TargetFileName)"  "$(SolutionDir)Plug-Ins\" /Y
    //      5)  Project, Properties, Build Events, Run the post-build event:, Always
    //      6)  Project, Properties, 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 = "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";
        }
    }
    

    Next add a Class Project called “PlugInC”, then include this code:

    • using System;
    • using System.ComponentModel.Composition;
    • using System.Windows.Forms;
    • using ContractInterfaces;
    • (namespace) PlugInC

    // Prerequisites to run:
    //      1)  Project, Add Reference, Projects, "ContractInterface"
    //      2)  Project, Add Reference, .NET, "System.Windows.Forms"
    //      3)  Project, Add Reference, .NET, "System.ComponentModel.Composition"
    //      4)  Project, Properties, Build Events, Post-Build event command line:
    //          xcopy "$(ProjectDir)$(OutDir)$(TargetFileName)"  "$(SolutionDir)Plug-Ins\" /Y
    //      5)  Project, Properties, Build Events, Run the post-build event:, Always
    //      6)  Project, Properties, 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 = "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";
        }
    }
    

    The Solution should look like this:

    Solution


    Right-click on the Solution, and select “Project Dependencies…”. Set the dependencies as follows:

    • MainProgram – depends on – ContractInterface
    • PlugInA – depends on – ContractInterface
    • PlugInB – depends on – ContractInterface
    • PlugInC – depends on – ContractInterface
    • ContractInterface – depends on – [nothing]

    Right-click on the Solution, and select “Project Build Order…”. The build order should be as follows:

    1. ContractInterface
    2. PlugInA
    3. PlugInB
    4. PlugInC
    5. MainProgram

    Build and run the program. You should see the 3 DLL files copied to a new “Plug-Ins” folder at the same directory level as the Solution file (*.sln). If not, check the Project Build Order, Dependencies, and that you entered the Post-Build Events according to the notes in the Plug-In code above. If the files are there, then the ListView should be populated in the Form with the Plug-In entries. Double-click each ListView entry to start the Plug-In.

    Have fun, I hope this helps someone….

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

This is .NET 2.0 WinForms. I have some code like so string str =
I have several WinForms .NET programs that are started using ClickOnce. The user logs
We have already shipped a client (.NET WinForms) application which sends customer data to
When creating an instance of a button within a .NET WinForms application, the .CausesValidation
NET WinForms. VB code: Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
I have a C# .net winforms application with two forms which connects to sql
This is a winforms vb.net application. Because of some limitations I am not able
I recently started learning about ASP.Net MVC and its various features MVC_3_MUSIC_STORE + CODE
I'm just getting started with ASP.NET MVC and am going through the NerdDinner tutorial.
I have a winform application (.NET 2.0 C#). From this application, I want to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.