最近,我開始將我的一個項目重組爲較小的程序集。在一個步驟中,我將視圖和視圖模型轉移到單獨的程序集中,同時將屬於一個視圖和VM的視圖和VM保留在一個通用程序集中。因此,我的項目結構是這樣的:CaliburnMicro在不同的程序集中找不到視圖模型的視圖
- 主要
- 核心
- 模塊< - 文件夾
- CharacterPresenter
- LocationPresenter
命名空間是這樣的:
- RpgTools
- 主要
- 的ViewModels
- 查看
- LocationPresenter
- 的ViewModels
- 查看
- 其他項目遵循相同的系統。
- 主要
「主」 包含引導程序和d簡約VM和視圖選擇的模塊。每位演示者都包含該演示者所需的所有視圖和視圖模型。 「核心」包含文件夾中每個項目使用的資源(例如元數據定義,導出界面等)
現在,在移動之後,Caliburn.Micro無法找到視圖模型的視圖,無論它有多簡單。這裏是一個視圖模型和視圖的例子:
namespace RpgTools.LocationPresenter.ViewModels
{
using System.ComponentModel.Composition;
using RpgTools.Core.Contracts;
[RpgModuleMetadata(Name = "Module C")]
[Export(typeof(IRpgModuleContract))]
public class ModuleCViewModel :IRpgModuleContract
{
}
}
<UserControl x:Class="RpgTools.LocationPresenter.Views.ModuleCView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock Text="ModuleC" />
</Grid>
</UserControl>
我每次加載模塊我得到以下錯誤:
Cannot find view for RpgTools.LocationPresenter.ViewModels.ModuleCViewModel.
如果我移動模型回「主」它工作得很好。由於它可能是引導程序的東西,這裏是它的完整代碼:
namespace RpgTools.Main
{
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;
using Caliburn.Micro;
using RpgTools.Core.Contracts;
/// <summary>The MEF bootstrapper.</summary>
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed. Suppression is OK here.")]
public class MefBootstrapper : BootstrapperBase
{
/// <summary>The composition container.</summary>
private CompositionContainer compositionContainer;
/// <summary>Initialises a new instance of the <see cref="MefBootstrapper"/> class.</summary>
public MefBootstrapper()
{
// this.CheckModuleDirectory();
this.Initialize();
}
/// <summary>Override to configure the framework and setup your IoC container.</summary>
protected override void Configure()
{
// Get the modules from the module directory
// ToDo: Implement dynamic loading from modules directory.
DirectoryCatalog dirCatalog = new DirectoryCatalog(@".");
// Create a combinable catalog
// ReSharper disable once RedundantEnumerableCastCall
AggregateCatalog catalog = new AggregateCatalog(AssemblySource.Instance.Select(s => new AssemblyCatalog(s)).OfType<ComposablePartCatalog>());
catalog.Catalogs.Add(dirCatalog);
// Create a new composition container.
// ReSharper disable once RedundantEnumerableCastCall
this.compositionContainer = new CompositionContainer();
// Create a new composition container.
this.compositionContainer = new CompositionContainer(catalog);
CompositionBatch compositionBatch = new CompositionBatch();
// Add window manager to composition batch.
compositionBatch.AddExportedValue<IWindowManager>(new ToolsWindowManager());
// Add EventAggregator to composition batch.
compositionBatch.AddExportedValue<IEventAggregator>(new EventAggregator());
// Add the container itself.
compositionBatch.AddExportedValue(this.compositionContainer);
// Compose the container.
this.compositionContainer.Compose(compositionBatch);
}
/// <summary>Override this to provide an IoC specific implementation.</summary>
/// <param name="service">The service to locate.</param>
/// <param name="key">The key to locate.</param>
/// <returns>The located service.</returns>
protected override object GetInstance(Type service, string key)
{
// Check if the contract is null or an empty string, if so return the contract name from the service itself.
string contractName = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(service) : key;
// Get a collection of exported values with the goven contract name.
IList<object> exports = this.compositionContainer.GetExportedValues<object>(contractName).ToList();
if (exports.Any())
{
return exports.First();
}
throw new Exception(string.Format("Could not locate any instances of contract {0}.", contractName));
}
/// <summary>Override this to provide an IoC specific implementation</summary>
/// <param name="serviceType">The service to locate.</param>
/// <returns>The located services.</returns>
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
return this.compositionContainer.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
}
/// <summary>Override this to provide an IoC specific implementation.</summary>
/// <param name="instance"> The instance to perform injection on.</param>
protected override void BuildUp(object instance)
{
this.compositionContainer.SatisfyImportsOnce(instance);
}
/// <summary>Override this to add custom behaviour to execute after the application starts.</summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The args.</param>
protected override void OnStartup(object sender, StartupEventArgs e)
{
this.DisplayRootViewFor<IShell>();
}
/// <summary>Checks if the modules directory exists and if not create it.</summary>
private void CheckModuleDirectory()
{
if (!Directory.Exists(@".\Modules"))
{
Directory.CreateDirectory(@".\Modules");
}
}
}
}
我可能會添加模塊發現工作正常。我ShellView模型顯示我加精每一個項目每一個模塊的意見只是裝不一樣,如果認爲位於不同的裝配比「主」
通過重寫工作,我解決原有問題SelectAssemblies()
方法用下面的代碼:
protected override IEnumerable<Assembly> SelectAssemblies()
{
var assemblies = Directory.GetFiles(ModuleDirectory, "*.dll", SearchOption.AllDirectories).Select(Assembly.LoadFrom).ToList();
assemblies.Add(Assembly.GetExecutingAssembly());
return assemblies;
}
但是現在我所有的模塊都被加載了兩次!這是我所做的代碼中的唯一更改。我做錯了什麼?
即使包含的ViewModels的組件還包含了看法? – Ruhrpottpatriot 2015-04-05 17:24:49
@Ruhrpottpatriot是的。如果我沒有記錯的話,給框架一個視圖模型,它的默認定位器使用它來查找視圖。它通過名稱空間執行此操作並搜索註冊的程序集。 – 2015-04-05 17:33:51
這個過程是否可以與目錄目錄一起工作?或者我必須通過'Assembly.Load()'加載所有程序集? – Ruhrpottpatriot 2015-04-05 17:50:02