Caliburn Micro - View & viewmodel in separate DLL

660 Views Asked by At

I've been trying this for a while and i have some issues. I have a project which dynamically loads 1 or more DLLs and I can't get the view binding to work.

I've overridden the SelectAssemblies method as such:

 protected override IEnumerable<Assembly> SelectAssemblies()
    {
        string[] AppFolders = Directory.GetDirectories(Config.AppsFolder);

        List<Assembly> assemblies = new List<Assembly>();
        assemblies.Add(Assembly.GetExecutingAssembly());

        foreach (string f in AppFolders)
        {
            Assembly ass = Directory.GetFiles(f, "*.dll", SearchOption.AllDirectories).Select(Assembly.LoadFrom).SingleOrDefault();
            if (ass != null)
            {
                assemblies.Add(ass);
            }
        }
        Apps = assemblies;
        return assemblies;
    }

This works as intended, i then have a method which runs on a button click which does:

public void OpenApp(string appName)
    {
        //AppName should be the same as the dll.

        string assName = string.Format("TabletApp.{0}", appName);

        Assembly ass = AppBootstrapper.Apps.SingleOrDefault(x => x.GetAssemblyName() == assName);

        if (ass != null)
        {
            dynamic vm = ass.CreateInstance(string.Format("TabletApp.{0}.ViewModels.{0}ViewModel", appName));
            IoC.Get<IWindowManager>().ShowDialog(vm);
        }
    }

This finds the viewmodel fine, however i get the error "unable to find contract for 'ExampleView'" when i load ExampleViewModel. I've also had to add [Export(typeof(view)] for each view in the base assembly since I've made this changes. It appears that Caliburn micro has stopped initialising views automatically.

Anyone know what i've done wrong?

1

There are 1 best solutions below

0
On BEST ANSWER

So it turns out i was doing nothing wrong, Along the way I've updated my caliburn.micro to 3.0.2. As it turns out a small change they made became a major breaking update. I wont go into it fully here other than to point out its the GetInstance in the bootstrapper that needs to be changed.

protected override object GetInstance(Type service, string key)
    {
        // Skip trying to instantiate views since MEF will throw an exception
        if (typeof(UIElement).IsAssignableFrom(service))
            return null;

        var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(service) : key;
        var exports = container.GetExportedValues<object>(contract);

        if (exports.Any())
            return exports.First();

        throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
    }

Please review the following link for more detailed information.

https://github.com/Caliburn-Micro/Caliburn.Micro/pull/339