F# partially implemented type

Mar 25, 2010 at 9:20 AM
Edited Mar 25, 2010 at 1:45 PM

Hi all,

I am working in VS2010 (.Net Framework 4) and have been trying to combine a C# console app with parts developed in F#.
(Until now, I have just been using an F# library that is used by parts developed in C# and this works fine).

Now, the architecture I have chosen is to have an interface, an abstract type implementing the interface and the actual parts inheriting from the abstract type (with InheritedExport)

I thought it should be possible to inherit from the abstract class in F# (by means of the "partially implemented type" construct) and this seems to work ok, but for some reason the parts do not show up in the DirectoryCatalog. The dlls are in the LoadedFiles collection and in the output window, I get the message "Symbols loaded".

Questions:
Can somebody confirm/deny that this should work?
Can the problem I am experiencing be related to the C# F# mixture and/or is there a way to find out why the parts are not discovered?

 

... Edit: I ended up starting from scratch with a small test project to see if I run into the same trouble; see next reply ...

 

Mar 25, 2010 at 1:52 PM
Edited Mar 25, 2010 at 1:54 PM

FYI: here a simplified solution that worked (I still have to figure out what is going wrong in my actual program, but it is definitely not the mixture of languages or the F# implementation of abstract classes, which is obviously good news :-)).
I can't upload any files, so I'll just paste the file contents... In my solution, each file is in a seperate project with interconnecting references

Program.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Text;

namespace MefTest
{
    class Program : IApplication
    {
        [ImportMany(typeof(IPlugin))]
        public List<IPlugin> Plugins { get; set; }

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

        public void Run()
        {
            Compose();
            foreach (IPlugin plugin in Plugins)
            {
                plugin.Initialize(this);
                Console.WriteLine(plugin.Name);
                plugin.Execute();
            }
        }

        private void Compose()
        {
            try
            {
                DirectoryCatalog catalog = new DirectoryCatalog(@"C:\Websites\PVForecast\MefTest");
                var container = new CompositionContainer(catalog);
                var batch = new CompositionBatch();
                batch.AddPart(this);
                container.Compose(batch);
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }
}

Interfaces.cs:

using System;
using System.ComponentModel.Composition;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MefTest
{
    public interface IApplication
    {
    }

    public interface IPlugin
    {
        string Name { get; set; }

        void Initialize(IApplication application);

        void Execute();
    }

    [InheritedExport(typeof(IPlugin))]
    public abstract class Plugin : IPlugin
    {
        protected string name;

        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        public abstract void Initialize(IApplication application);

        public abstract void Execute();
    }
}

 Plugin1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;

namespace MefTest
{
    [Export(typeof(IPlugin))]
    public class Plugin1 : IPlugin
    {
        private string name;

        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        public void Initialize(IApplication application)
        {
            name = "Plugin1";
        }

        public void Execute()
        {
            Console.WriteLine("Hi from Plugin1");
        }
    }
}

Plugin2.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MefTest
{
    public class Plugin2:Plugin
    {
        public override void Initialize(IApplication application)
        {
            name = "Plugin2";
        }

        public override void Execute()
        {
            Console.WriteLine("Hi from Plugin2");
        }
    }
}

Plugin3.fs
namespace MefTest

open System
open System.Collections.Generic

type public Plugin3() =
    inherit Plugin()

    override this.Initialize(application:IApplication) =
        this.Name <- "Plugin3"

    override this.Execute() =
        Console.WriteLine("Hi from Plugin3")