【问题标题】:WPF - MVVM multiple projects structureWPF - MVVM 多项目结构
【发布时间】:2015-05-06 13:14:42
【问题描述】:

我总是在一个项目中使用 MVVM 开发应用程序,并将 Model、View、ViewModel 与文件夹分开。通过查看不同的问题和不同的书籍,我了解到,出于不同的原因,将它们分开放在不同的项目中会更好,因此我尝试开发一个简单的项目来看看它是如何工作的。

首先,我创建了一个包含不同文件夹的项目,然后我启动了应用程序,它运行良好。 这是我省略了模型文件夹的“单个项目”的结构。

在我创建了由这 3 个项目组成的多个项目之后:

-MVVM

-MVVM.Views

-MVVM.ViewModels

这就是我构建“多个项目”的方式

我将 MVVM.Views,MVVM.ViewModels 输出类型设置为 Dll 而不是 .exe,我在 MVVM 中添加了项目(MVVM.Views,MVVM.ViewModels) 引用。

但是当我午餐应用程序时,我得到一个错误

“System.Exception”类型的未处理异常发生在 WindowsBase.dll 信息:找不到任何实例 合约 MVVM.ViewModels.IShell.

我也在使用 Caliburn.Micro 2.0.2 作为引导程序,这是 MefBootstrapper:

public class MefBootstrapper : BootstrapperBase
{
    private CompositionContainer container;

    public MefBootstrapper()
    {
        Initialize();
    }

    protected override void Configure()
    {
        var catalog = new AggregateCatalog(
                AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()
                );

        container = new CompositionContainer(catalog);

        var batch = new CompositionBatch();

        batch.AddExportedValue<IWindowManager>(new WindowManager());
        batch.AddExportedValue<IEventAggregator>(new EventAggregator());
        batch.AddExportedValue(container);

        container.Compose(batch);


        }

        protected override object GetInstance(Type serviceType, string key)
        {
            string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
            var exports = container.GetExportedValues<object>(contract);

            if (exports.Count() > 0)
                return exports.First();

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

        protected override IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
        }

        protected override void BuildUp(object instance)
        {
            container.SatisfyImportsOnce(instance);
        }

        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewFor<IShell>();
        }
    }

这是 ViewModel 代码

namespace MVVM.ViewModels
{
    public interface IShell { }

    [Export(typeof(IShell))]
    public class MainViewModel : PropertyChangedBase, IShell
    {

    }
}

我想了解我错在哪里?我错过了一步?感谢支持

【问题讨论】:

  • 请提供 ViewModel 代码。此外,在单独的项目中使用 ViewModel 也是有争议的做法。包括我自己在内的许多 WPF MVVM 开发人员都将 VM 视为与 View 相关联的组件并使其保持耦合(甚至还有一个插件可以将 ViewModel 保持在 XAML 之后,在代码隐藏旁边)。但是,嘿,一般来说,无论如何你都会使用带有额外控制器的 MVCVM,然后控制器会转到单独的项目。
  • 我添加了代码。我总是使用单个项目,因为它更容易和快速,但是阅读我理解最好将视图与视图模型和模型分开,我也想学习这种但我不确定将来我会用这种方式。
  • 分离到项目中是一种很好的做法。我只是说 ViewModels 属于“视图”项目。模型、DAL 等应该都是独立的项目。
  • 所以你说我应该在 MVVM.Views 项目中使用 ViewModels 文件夹?
  • 我不知道关于 CM 的工作表,但我知道在运行时使用反射来加载类型。如果您的应用程序中有两个程序集,A.EXE 和 B.DLL,并且您想在 A.EXE 中加载 B.DLL 中定义的类型,则必须将 B.DLL 加载到 AppDomain 中才能访问那些类型。 CM 可能正在寻找实现 IShell 的 appdomain 中的类型,但是 MVVM.ViewModels 不会加载到可执行文件的 appdomain 中,并且 CM 不会加载随机程序集来寻找它。解决方案?有很多,不确定哪个最适合您。

标签: c# wpf mvvm caliburn.micro


【解决方案1】:

我发布答案以防万一有人遇到我同样的问题。在阅读了很多帖子和不同的东西后,我发现了错误。我忘记将程序集加载到应用程序中。这真的很容易,只需在此处更改 Configure() void 代码:

protected override void Configure()
{
    string pluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "");
    if (!Directory.Exists(pluginPath))
        Directory.CreateDirectory(pluginPath);

    var fi = new DirectoryInfo(pluginPath).GetFiles("*.dll");
    AssemblySource.Instance.AddRange(fi.Select(fileInfo => Assembly.LoadFrom(fileInfo.FullName)));

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

    container = new CompositionContainer(catalog);

    var batch = new CompositionBatch();

    batch.AddExportedValue<IWindowManager>(new WindowManager());
    batch.AddExportedValue<IEventAggregator>(new EventAggregator());
    batch.AddExportedValue(container);

    container.Compose(batch);
}

【讨论】:

    猜你喜欢
    • 2013-09-20
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多