This project is read-only.

How can I register this export type

Nov 28, 2014 at 10:20 AM
Edited Nov 28, 2014 at 10:21 AM
Hello,
I've a WPF application that uses MVVM with Caliburn Micro, I've the viewmodels that inherits from SimpleScreen<T> where T is the type of the data presented in the viewmodel... now the simple screen implements IMenuItem that has a property MenuId of type string...

when I'm builing up the menu I was getting all the instance of type IMenuItem (using MEF for composition)

Now when I try to register the viewmodel for type IMenuItem I got

"The supplied type SimpleScreen<TViewModel> is an open generic type. This type cannot be used for registration using this method. You can use one of the SimpleInjector.Extensions.OpenGenericRegistrationExtensions.RegisterOpenGeneric extension method overloads for mapping an generic abstraction to an generic implementation, or use one of the SimpleInjector.Extensions.OpenGenericBatchRegistrationExtensions.RegisterManyForOpenGeneric extension method overloads for registering a set of implementations for a generic abstraction.\r\nParameter name: implementationType"}

Now I don't register direcly SimpleScreen<T> but on IMenuItem

[omiss]
            var executingAssembly = Assembly.GetExecutingAssembly();


            var tof = typeof(IMenuItem);
            var ax = executingAssembly.GetTypes().Where(x => tof.IsAssignableFrom(x));
           
            foreach(var x in ax)
            {
                ContainerInstance.Register(tof, x, Lifestyle.Transient);
            }

[omiss]

  public class SimpleScreen<T> : ScreenBase<SimpleScreen<T>>
  {
      [omiss]
  }

public class ScreenBase<TViewModel> : Screen, IMenuItem, IDataErrorInfo, IDockingSerializationTag, IViewModelParameters, IPersistence
        where TViewModel : ScreenBase<TViewModel>
{
     [OMISS]
}
How can I register this?

Thanks
Nov 28, 2014 at 11:18 AM
How many IMenuItem implementations do you have? Are there any non-generic implementations? Can you show such implementation?
Nov 28, 2014 at 11:21 AM
Hello,
for example I've got
   public class DealGDEMViewModel : SimpleScreen<DealGdem>
    {
    }

or 

   public class CheckGaranzieCCGSintesiViewModel : SimpleScreen<CheckGaranzieSintesiResult>
    {
    }

There're around 120 implementation , yes they're real implementation...
Nov 28, 2014 at 11:22 AM
And what is the abstrsction you use to inject them into consumers?
Nov 28, 2014 at 11:24 AM
The IMenuItem interface which is defined in the base class (ScreenBase<T>)
Nov 28, 2014 at 11:29 AM
But if you use this non-generic IMenuItem abstraction, how do you distinguish between all the implementations you have. I would expect that your consumers would depend on something like IScreen<T> or IMenuItem<T>. Or do work with the complete collection of menu items? Can you show an example of what you are doing? This helps me understand your use case and allows me to show you what you need.
Nov 28, 2014 at 3:07 PM
here I'm ...

when I click on a menu item a MenuMessage is processed (via Caliburn micro's IHandle<T>) as
    public void Handle(MenuMessage message)
        {
            Type typeSpecific = null;

            if (!(message is BODDiagnosticMenuMessage))
            {
                typeSpecific = message.MenuItemType;
            }

            else //it's a bod message, I've to threat it differently
            {
                var bod = message as BODDiagnosticMenuMessage;
                typeSpecific = GetTypeFromStoredProcedureType(bod.IDStoredProcedureType);
            }

            if (message.ShowInDialog)
            {
                var s = (Screen)Activator.CreateInstance(typeSpecific, string.Empty);
                windowManager.ShowWindow(s);
                return;
            }

            IScreen screen = null;

            var contract = AttributedModelServices.GetContractName(typeSpecific);
            var exports = DOMEBootStrapper.Container.GetExportedValues<object>(contract);
            if (exports.Any())
                screen = (Screen)exports.First();

            if (null != screen)
            {
                if (message.CloseMessageRequest)
                {
                    if (screen is IOpenedFromAnotherView)
                    {
                        ((IOpenedFromAnotherView)screen).UniqueID = message.UniqueID;
                    }

                    DeactivateItem(screen, true);
                }
                else
                {
                    if (screen is IOpenedFromAnotherView)
                    {
                        ((IOpenedFromAnotherView)screen).UniqueID = Guid.NewGuid();
                    }

                    if (screen is IViewModelParameters)
                    {
                        ((IViewModelParameters)screen).ViewModelParameters = message.Parameters;
                    }

                    ActivateItem(screen);
                }
            }
        }
The menu Items are created when the MenuViewModel is created in this method
 private async Task GetMenuItems()
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();

            string xmlFileName = string.Format("DOME.Xml.NewMenuStructure.xml");

            DOMEMenuItemCollection collection = null;

            var doc = new XmlDocument();

            using (Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(xmlFileName))
            {
                if (stream != null)
                {
                    using (var reader = new StreamReader(stream))
                    {
                        doc.LoadXml(reader.ReadToEnd());
                    }
                }
            }


            IEnumerable<Lazy<IMenuItem>> menuItems = DOMEBootStrapper.Container.GetExports<IMenuItem>();

            var lst = new List<IMenuItem>();
            foreach (var m in menuItems)
            {
                lst.Add(m.Value);
            }

            DOMEMenuItem menuRoot = BuildMenu(doc.SelectSingleNode(@"/Node"), "/", lst);
            collection = menuRoot.Items;

            AddSystemMenuItems(collection);
            try
            {
                await AddDiagnosticoMenuItems(collection);
                await AddTabelleMenuItems(collection);
            }
            catch (Exception ex)
            {
                errorHandler.HandleErrorAsync(ex);
            }

            Items = collection;
        }
Nov 28, 2014 at 3:23 PM
Seems to me that you need to register your IMenuItem implementations as a collection of IMenuItem. For instance like this:
container.RegisterAll<IMenuItem>(
    from type in executingAssembly.GetTypes()
    where typeof(IMenuItem).IsAssignableFrom(type)
    where !type.IsAbstract && !type.IsGenericTypeDefinition
    select type);
Dec 1, 2014 at 8:14 AM
Hello,
this worked like a charm! thanks....another question...since I've got some repositories that implement a IRepostiroryABC ... how can I scan the assembly and get all the method that implements an interface and register it?

Thanks
Dec 1, 2014 at 8:22 AM
If you need to register many implementations for one open-generic abstraction, you can use the RegisterManyForOpenGeneric extension method. In case the implementations have no related interfaces, you need to do it yourself using reflection, just like the example you are already using.
Dec 1, 2014 at 8:37 AM
No, I mean...

I've got
public class RepositoryOne : IRepositoryOne
public class RepositoryTwo : IRepositoryTwo
I've no generic repository
Dec 1, 2014 at 9:01 AM
Yes, I understand. You need to reflect over the application yourself, for instance:
var repoRegistrations =
    from type in typeof(RepositoryOne).Assembly.GetExportedTypes()
    where type.Name.StartsWith("Repository")
    select new { Service = type.GetInterfaces().Single(), Impl = type };

repoRegistrations.ToList().ForEach(r => container.Register(r.Service, r.Impl));
Dec 1, 2014 at 9:46 AM
but I don't have only repositorty one...I need when I have IRepositoryOne to register RepositoryOne, when IRepositoryTwo to register IRepositoryTwo and so on....