0
votes

Hi try port my Winform app to WPF with MVVM. I use Caliburn Micro and MEF as IoC. I have service in external dll -> Pokec_Toolki.dll and this services use other external dll such as JSON.NET, HtmlAgilityPack..etc (third party libraries).

My service look like this:

public interface IPokecConnection
{
    PokecAccount LogOn(string nick, string password);
    bool LogOff(PokecAccount account);
}

[Export(typeof(IPokecConnection))]
public class PokecConnection : IPokecConnection
{
}

For my Service I create consumer for class PokecConnection, it is in the same assembly as Service:

[Export]
public class PokecConnectionConsumer
{
    private readonly IPokecConnection _pokecConn;

    [ImportingConstructor]
    public PokecConnectionConsumer(IPokecConnection pokecConn)
    {
        _pokecConn = pokecConn;
    }

    public PokecAccount MethodWrapperForLogOn(string name, string  password)
    {
        return _pokecConn.LogOn(name, password);
    }

}

I have simple view with 2 textbox and 1 button. I bind event click of button with caliburn convention on view-model.

View:

<Button Micro:Message.Attach="[Event Click]=[Action LogOn(tbNick.Text,tbPassword.Text)]"
        Content="Prihlás ma"
        Width="100" 
        Grid.Row="2"
        Height="25" Margin="4,4,4,4" />

I need consume service method in my view model. So in view-model I have this:

[Export(typeof(IShellViewModel))]
public class ShellViewModel : Screen, IShellViewModel, IDataErrorInfo
{

    private PokecConnectionConsumer _connConsumer;

    protected override void OnInitialize()
    {
        base.OnInitialize();

        var mycatalog = new AssemblyCatalog(System.Reflection.Assembly.LoadFrom("Pokec_Toolkit.dll"));

        var container = new CompositionContainer(mycatalog);
        container.ComposeParts(this);

        _connConsumer = container.GetExportedValue<PokecConnectionConsumer>();
    }

    //this method is bind on event click of button in view
    public void LogOn(string nick, string password)
    {
        //call method LogOn from class PokecConnection in external dll through PokecConnectionConsumer

        var accout = _connConsumer.MethodWrapperForLogOn(nick, password);

        // in this place if account is not null, I need close this view and create new view MainView 
        //a send to the MainViewModel constructor as argument variable account

        //some test 
        MessageBox.Show(accout.SessionId);
    }


}

I have these question:

  1. First, It is good create consumer for service class in external dll? In my case PokecConnectionConsumer **and this class is in same assembly as service class PokecConnection?
  2. It is correct way to load external assembly in view-model in method OnInitialize?
  3. It is correct call service method in view-model?
  4. It exist more suitable way how bind method from external dll on view control ? I need simple load external dll in wpf app with MVVM and bind service method on controls in views. What is the best way?

How can I close actual view and create new view, also activate this view. I need send as argument variable from view-model to another vie-model constructor.**

MY SOLUTION:

I create interface assembly and refer this assembly in external service dll and also in wpf app.

In bootstraper I load this assembly with reflection:

    var catalog =
    new AggregateCatalog(
        AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());

catalog.Catalogs.Add(
    new AssemblyCatalog(string.Format(
        CultureInfo.InvariantCulture, "{0}{1}", System.IO.Directory.GetCurrentDirectory(), @"\Pokec_Toolkit.dll")));

_container = new CompositionContainer(catalog);

Than I create conductor class:

public interface IShellViewModel
{
    void ShowLogOnView();
    void ShowMessengerView();
}

[Export(typeof(IShellViewModel))]
public class ShellViewModel : Conductor<IScreen>, IShellViewModel
{
    public ShellViewModel()
    {
        ShowLogOnView();
    }

    public void ShowLogOnView()
    {
        ActivateItem(IoC.Get<LogOnViewModel>());
    }

    public void ShowMessengerView()
    {
        ActivateItem(IoC.Get<MessengerViewModel>());
    }
}

And in view-model I have this:

  [Export]
    public class LogOnViewModel : Screen, IDataErrorInfo, ILogOnViewModel
    {

        [Import]
        private IShellViewModel _shellViewModel;

        [Import]
        private IPokecConnection _pokecConn;

//this method is bind on event click of button
        public void LogOn(string nick, string password)
        {
            //SHOW NEW WIEW
           _shellViewModel.ShowMessengerView();
        }
    }
1

1 Answers

0
votes

1) Yes, so that if the external dependency changes, you do not have to recompile your UI. Also it must be outside View/VM logic.

2) Not I am afraid. Create a separate service class for it.

3) Same, Create a separate service class for it and use within VM.

4) Well, you have to load a DLL anyway. So load it in the service class.