New Posts New Posts RSS Feed: Exporting templated class
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Exporting templated class

 Post Reply Post Reply
Author
pponzano View Drop Down
Senior Member
Senior Member
Avatar

Joined: 28-Apr-2011
Location: Italy
Posts: 165
Post Options Post Options   Quote pponzano Quote  Post ReplyReply Direct Link To This Post Topic: Exporting templated class
    Posted: 18-Dec-2012 at 1:27am
Hello,
I'm lost in a cave with Exporting with templates...

before I have had an interface of type IDashboard that has an ID (int) and a collection of Items of type Gauge

Now I've been asked if it's possible to define another type of Gauge and continue using existing code structure..so I've defined those class


  [Export(typeof(IDashBoard<Gauge<ISnapshot>, ISnapshot>))]
    public class DashboardViewModel : DashBoardBase<Indicatore<SNAPSHOT_INDICATORE_SELECT_Result>, SNAPSHOT_INDICATORE_SELECT_Result>
    {
...
}

 public class DashBoardBase<T,Y> : Screen, IDashBoard<T, Y>
        where T : GaugeBase<Y>
        where Y : ISnapshot
    {
...
}

 public class GaugeBase<T> : INotifyPropertyChanged where T:ISnapshot
 {
...
}

 public interface ISnapshot
    {
        DateTime DT_TS { get; set; }
    }

public interface IDashBoard<T,Y> : INotifyPropertyChanged
    where T : GaugeBase<Y>
    where Y : ISnapshot
{
    BindableCollection<T> DataItems { get; set; }

    T SelectedDataItem { get; set; }

    int IdDashBoard { get; set; }

    int IdLayout { get; }
...
}


Before I had a dashboardfactory of type


        [ImportingConstructor]
        public DashBoardFactory()
        {
            //[ImportMany(typeof(IDashboard))] IEnumerable<IDashboard listaIndicatori
            this.listaIndicatori = listaIndicatori;
        }

and it was working... now I've tried all the ways but I'm not able to set the export so that my dashboardfactory can get items

   [ImportingConstructor]
        public DashBoardFactory()
        {
            //[ImportMany(typeof(DashBoardBase<GaugeBase<ISnapshot>, ISnapshot>))] IEnumerable<DashBoardBase<GaugeBase<ISnapshot>, ISnapshot>> listaIndicatori
            this.listaIndicatori = listaIndicatori;



            var items = Cocktail.Composition.GetInstances<IDashBoard<Indicatore<ISnapshot>, ISnapshot>>();
            int count = items.Count(); //0 or it says it cannot cast to type...
  
        }

Any suggestion?
Thanks
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post Posted: 18-Dec-2012 at 8:29am
Based on what you are showing here, you are exporting as IDashBoard<Gauge<ISnapshot>, ISnapshot>)) and the only line that isn't commented out is where you are trying to get instances of type IDashBoard<Indicatore<ISnapshot>, ISnapshot> directly from Cocktail.Composition. Those are not the same type contracts, so you won't get anything. The export and import contracts must match. You can also export/import by name if the type is too restrictive.
 
[Export("Foo")]
public class SomeClass {}
 
[Export]
public class AnotherClass
{
     [ImportingConstructor]
     public AnotherClass([Import("Foo")] object foo) {}
}
 
The other option is open generics if you are developing on .NET 4.5. Unfortunately, open generics are not supported on Silverlight.
 
[Export(typeof(IDashBoard<,>)]
public GenericDashBoard<T, Y> : IDashBoard<T,Y>
{
}
 
[Export]
public class Foo
{
    [ImportingConstructor]
    public Foo(IDashBoard<Indicatore<ISnapshot>, ISnapshot> dashboard) {}
}


Edited by mgood - 18-Dec-2012 at 8:30am
Back to Top
giotis View Drop Down
Groupie
Groupie
Avatar

Joined: 26-Apr-2012
Location: Greece
Posts: 53
Post Options Post Options   Quote giotis Quote  Post ReplyReply Direct Link To This Post Posted: 21-Dec-2012 at 4:20pm
I tried by your example, to create generic ViewModel but failed

  [Export(typeof(
GridViewViewModel<>))]
  public class GridViewViewModel<T> : Screen, IHandle<SavedMessage> where T : DomainModel.EntityBase    {

      ..... copy from StaffingResourceSearchViewModel

or with I
nterface

 public interface IGridView<T>   {
        void Start();
        T CurrentStaffingResource { get; set; }
        event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    }

  [Export(typeof(IGridView<>))]
  public class GridViewViewModel<T> : Screen,
IGridView<T>, IHandle<SavedMessage> where T :   DomainModel.EntityBase    {
  ....
 
            var viewModel= Composition.GetInstance<IGridView<DomainModel.StaffingResource>>();
            viewModel is null

            MEF don't create viewModels?

 In fact is possible?

thank you for your time
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post Posted: 21-Dec-2012 at 5:11pm
Which version of Cocktail are you using? You need to use 2.0.5 or higher. There was a fix in 2.0.5 for this, see release notes.
 


Edited by mgood - 21-Dec-2012 at 5:15pm
Back to Top
giotis View Drop Down
Groupie
Groupie
Avatar

Joined: 26-Apr-2012
Location: Greece
Posts: 53
Post Options Post Options   Quote giotis Quote  Post ReplyReply Direct Link To This Post Posted: 21-Dec-2012 at 6:05pm
Cocktail 2.2.0

I looked at Cocktail sourse code(Test project) but not work
is still null

any other example to working ?


Edited by giotis - 21-Dec-2012 at 6:15pm
Back to Top
giotis View Drop Down
Groupie
Groupie
Avatar

Joined: 26-Apr-2012
Location: Greece
Posts: 53
Post Options Post Options   Quote giotis Quote  Post ReplyReply Direct Link To This Post Posted: 21-Dec-2012 at 7:36pm
I want to create Generic ViewModels

or I making wrong to follow this way?

any help Marcel ?
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post Posted: 22-Dec-2012 at 12:12am
Here's a very silly example that works just fine for me. I'm not sure what's going on with your code. There's something you are not showing me. 

using System.ComponentModel.Composition;
using Caliburn.Micro;
using Cocktail;
using IdeaBlade.EntityModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;

public interface IGridView<T>  where T : IEntity
{
    T CurrentEntity { get; }
}

[Export(typeof(IGridView<>))]
public class GridView<T> : Screen, IGridView<T> where T : IEntity
{
    private readonly IDialogManager _dialogManager;
    private T _currentEntity;

    [ImportingConstructor]
    public GridView(IDialogManager dialogManager)
    {
        _dialogManager = dialogManager;
    }

    public T CurrentEntity
    {
        get { return _currentEntity; }
        private set
        {
            if (Equals(value, _currentEntity)) return;
            _currentEntity = value;
            NotifyOfPropertyChange(() => CurrentEntity);
        }
    }
}

namespace GenericExportTests
{
    [TestClass]
    public class GenericExportExample
    {
        [TestMethod]
        public void ShouldInstantiateGenericViewModel()
        {
            var bootstrapper = new CocktailMefBootstrapper<object>(false);
            var instance = Composition.GetInstance<IGridView<Customer>>();

            Assert.IsNotNull(instance);
        }
    }
}

Back to Top
giotis View Drop Down
Groupie
Groupie
Avatar

Joined: 26-Apr-2012
Location: Greece
Posts: 53
Post Options Post Options   Quote giotis Quote  Post ReplyReply Direct Link To This Post Posted: 22-Dec-2012 at 11:52am
Marcel, many thanks

I dont know very well MEF

but when run your example I take back an error "could not locate any instances of contract ...

after add in Appbootstraper
            batch.AddExportedValue<IGridView<Customer>>(new GridView<Customer>(null) ); only for test

is ok.


I use the latest version of TempHire (vs2012)

  a).I hide the "StaffingResourceSearchViewModel" and I create new one like your example
            
             public interface IGridViewGeneric<T>  where T : EntityBase{
                   T CurrentEntity { get; }
             }

             [Export(typeof(IGridViewGeneric<>))]
             public class GridViewGenericViewModel<T> : Screen, IGridViewGeneric<T> where T : EntityBase
             {...

b)Create a new view named GridViewGenericView

b).I changed the  "ResourceMgtViewModel"
 [ImportingConstructor]
        public ResourceMgtViewModel(IGridViewGeneric<DomainModel.StaffingResource> searchPane, .....


but took back the same error "could not locate any instances of contract IGridViewGeneric<DomainModel.StaffingResource...

I think MEF dont find the instance
If you like to anwser me please with TempHire example (I mean temphire entities)





Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post Posted: 22-Dec-2012 at 4:49pm
At this point I'm at a loss as to what you are doing wrong. The example I gave you works just fine. You can download the entire solution from my Skydrive (http://sdrv.ms/VZ1pSj). If this doesn't work than I don't know. I also have two unit tests in the Cocktail test project to ensure open generics work and those tests pass. I can't spend more time on samples. You gonna have to hire one of our consultants to teach you MEF as so far there doesn't appear to be a bug in Cocktail's handling of open generics.
Just to reiterate, I hope you are not trying to do anything of this in Silverlight, because this won't work in Silverlight as I mentioned before. This will only work in a WPF 4.5 (and Windows 8 Store) applications.


Edited by mgood - 22-Dec-2012 at 5:20pm
Back to Top
giotis View Drop Down
Groupie
Groupie
Avatar

Joined: 26-Apr-2012
Location: Greece
Posts: 53
Post Options Post Options   Quote giotis Quote  Post ReplyReply Direct Link To This Post Posted: 22-Dec-2012 at 5:40pm
not in SilverLight

your sample is perfect , work in this case

but something missing when run under TempHire

I ll try to help you for you help me
I check the Composition and the Catalog have the part GridView({0}) - exist !

but when     ...      var instance = Composition.GetInstance<IGridView<Foo>>();
error "Could not locate any instances of contract IGridView<Foo...

very sorry if I spend your time
many thanks



Edited by giotis - 22-Dec-2012 at 5:42pm
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post Posted: 22-Dec-2012 at 6:10pm
Ok, I was able to reproduce the issue. TempHire uses the InterceptingCatalog from MefContrib and it looks like it is causing this issue. Unfortunately, the MefContrib project is dead, so this won't get fixed. If you want to use open generics, you gonna have to forgo the use of the InterceptingCatalog. I know of at least one other person who was having issues in their application because of the InterceptingCatalog. I will remove it from future versions in order to discourage its use.
 
If you comment out the following method in BootstrapperBase<T> it should work, but now you gonna have to manually subscribe all your ViewModels that receive messages from the EventAggregator with a call to EventFns.Subscribe(this) in the constructor.
 
        protected override ComposablePartCatalog PrepareCompositionCatalog()
        {
            var cfg = new InterceptionConfiguration().AddInterceptor(this);
            return new InterceptingCatalog(base.PrepareCompositionCatalog(), cfg);
        }
Back to Top
giotis View Drop Down
Groupie
Groupie
Avatar

Joined: 26-Apr-2012
Location: Greece
Posts: 53
Post Options Post Options   Quote giotis Quote  Post ReplyReply Direct Link To This Post Posted: 22-Dec-2012 at 7:33pm
What can I say, you're huge, you're beautiful, you covered the issue 100%,
something good came out of our discussion,
must fix the code because it is too painful to remember to subscribe each time there IHandle.
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down