Search code examples
c#inversion-of-controlmefioc-container

How to pass a function to another class using IoC


I am trying to implement inversion of control (IoC) in order to develop a plug-in based application, which needs to be able to pass data (e.g. strings) back to my main EXE when something happens. To achieve this, I am passing an Action to the DLL which it can use to send data back to the EXE. The following code shows a little test application to explain my beginner-problem:

namespace MainExe
{
    class Program
    {
        [Import(typeof(IDataProvider))]
        public IDataProvider stringProvider { get; set; }

        public void myCallback(string str)
        {
            Console.WriteLine(str);
        }

        public Program()
        {
            try
            {
                AggregateCatalog aggregatecatalogue = new AggregateCatalog();
                aggregatecatalogue.Catalogs.Add(new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory));
                CompositionContainer container = new CompositionContainer(aggregatecatalogue);
                container.ComposeParts(this);    
            }
            catch (FileNotFoundException fnfex)
            {
                Console.WriteLine(fnfex.Message);
            }
            catch (CompositionException cex)
            {
                Console.WriteLine(cex.Message);
            }
        }

        void Run()
        {
            if (stringProvider != null)
            {
                stringProvider.SaySomething("myrequest", myCallback);
                Console.ReadKey();
            }
        }

        static void Main(string[] args)
        {
            Program program = new Program();
            program.Run();
        }
    }
}

My Interface looks like this:

namespace DataInterfaceDll
{
    public interface IDataProvider
    {
        void SaySomething(string request, Action<string> callback);
    }
}

And this is the Plug-In (DLL), which should be able to send something back to the EXE (or call a function from the EXE that does this):

namespace StringDataDll
{
    [Export(typeof(IDataProvider))]
    public class StringData : IDataProvider
    {
        public void SaySomething(string request, Action<string> callback)
        {
            callback("This is just a test program...");
        }
    }
}

When I run this code, I get a System.Reflection.ReflectionTypeLoadException in the following line

container.ComposeParts(this);

Can anyone tell me what I am doing wrong here?


Solution

  • It works for me by loading dynamically the DLL.

    aggregatecatalogue.Catalogs.Add(new AssemblyCatalog(Assembly.LoadFile("yourpath\StringDataDll.dll")));
    aggregatecatalogue.Catalogs.Add(new AssemblyCatalog(Assembly.GetAssembly(typeof(IDataProvider))));
    

    And it works too with new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory) when you copy the stringDataDll.dll in the output folder of your main program.

    Be sure to have all of your dll files in your output folder of your main program.