试图在Caliburn.Micro中使用DesignTime支持时如何解决IoC异常?

问题描述:

由于某些原因,当尝试在Caliburn.Micro中使用设计时支持时,会发生IoC异常。试图在Caliburn.Micro中使用DesignTime支持时如何解决IoC异常?

bei Caliburn.Micro.IoC。 < .cctor> b__1(Type service)bei Caliburn.Micro.ViewLocator。 < .cctor> b__2(Type viewType)bei Caliburn.Micro.ViewLocator。 (类型modelType, DependencyObject displayLocation,Object context)bei Caliburn.Micro.ViewLocator。 < .cctor> b__a(对象模型,DependencyObject的 displayLocation,对象上下文)贝 Caliburn.Micro.View.OnModelChanged(DependencyObject的targetLocation, DependencyPropertyChangedEventArgs参数)贝 System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs E)贝 系统.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs E)贝 System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs 参数)贝 System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex,的DependencyProperty DP,PropertyMetadata元数据, EffectiveValueEntry oldEntry,EffectiveValueEntry & newEntry,布尔 coerceWithDeferredReference,布尔coerceWithCurrentValue, OperationType operationType)贝 System.Windows.DependencyObject.InvalidateProperty(的DependencyProperty DP,布尔preserveCurrentValue)贝 System.Windows.Data.BindingExpressionBase.Invalidate(布尔 isASubPropertyChange)贝 System.Windows.Data.BindingExpression.TransferValue(对象NEWVALUE, 布尔isASubPropertyChange)贝 System.Windows.Data.BindingExpression.Activate(对象项)贝 System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt 尝试)bei System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)bei MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)bei MS.Internal.Data.DataBindEngine.Run (对象ARG)
贝MS.Internal.Data.DataBindEngine.OnLayoutUpdated(对象发件人, EventArgs的)贝 System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()贝 System.Windows.ContextLayoutManager.UpdateLayout()贝 系统。 Windows.UIElement.UpdateLayout()

我想启用DesignTime支持,如文档here我的窗口,其中包含一个ContentControl中:

<Window x:Class="Test.MyShellView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:cal="http://www.caliburnproject.org" 
     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:viewModels="clr-namespace:Test.DesignData.ViewModels" 
     mc:Ignorable="d" 
     ResizeMode="CanResizeWithGrip" 
     d:DataContext="{d:DesignInstance Type=viewModels:DesignShellViewModel, IsDesignTimeCreatable=True}" 
     cal:Bind.AtDesignTime="True"> 


    <ContentControl cal:View.Model="{Binding ActiveItem}" /> 

</Window> 

这是用于在运行具有以下视图模型:

public class MyShellViewModel : ShellViewModel // derrived from own base class 
{ 
    public MyShellViewModel(IThemeManager themeManager) 
     : base(themeManager) 
    { 
    } 
} 

,但认为应该结合对这个视图模型在命名空间DesignData设计时间:

public sealed class DesignShellViewModel : Conductor<IScreen>.Collection.OneActive 
{ 
    public DesignShellViewModel() 
    { 
     AssemblySource.Instance.Add(this.GetType().Assembly); 

     this.ActivateItem(new TestViewModel()); 
    } 
} 

这是包含在测试单个筛网(一个TestViewModel) 一个简单的导体。DesignData命名空间:

​​

和相应的视图

<UserControl x:Class="Test.DesignData.Views.TestView" 
      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 VerticalAlignment="Center" HorizontalAlignment="Center">It's working at design time!</TextBlock> 
    </Grid> 
</UserControl> 

任何人谁知道这个问题可能是什么?

编辑:由mvermef帖子给我带来了更接近解决方案(我认为)

现在出现一条消息,卡利是无法找到视图模型视图(就像它在运行时,当名称为错误或类未找到/丢失......但它在同一个库中)。

下面是提问者@mvermef我引导程序的一部分:

// nothing special here, is empty... just a concrete class to create it via Xaml 
public class Bootstrapper : Bootstrapper<IShell> 
{ 
} 

// contains the important parts (Autofac, MEF integration etc.) 
public class Bootstrapper<TViewModel> : BootstrapperBase 
{ 
    // I use Common.Logging 
    private static readonly ILog Log = LogManager.GetLogger(typeof(Bootstrapper<TViewModel>)); 

    // the Autofac container 
    private IContainer container; 

    static Bootstrapper() 
    { 
     // Redirect the default log output of Caliburn and use Common.Logging instead 
     Caliburn.Micro.LogManager.GetLog = type => new CommonLoggingAdapter(type); 
    } 

    protected Bootstrapper() 
    { 
     this.Initialize(); 
    } 

    protected override void Configure() 
    { 
     var builder = new ContainerBuilder(); 

     var catalogs = new List<ComposablePartCatalog>(); 

     // Register basic services required by Caliburn 
     builder.RegisterType<WindowManager>() 
      .As<IWindowManager>() 
      .InstancePerLifetimeScope(); 

     builder.RegisterType<EventAggregator>() 
      .As<IEventAggregator>() 
      .InstancePerLifetimeScope(); 

     if (Execute.InDesignMode) 
     { 
      // code that follows next should not execute in Design Mode, so I jump over (thanks to mvermev, the Exception is gone because of this => but still the problem with the missing View) 
      return; 
     } 
     ... 
    } 

    protected TInstance Get<TInstance>(string key = null) 
    { 
     return (TInstance)this.GetInstance(typeof(TInstance), key); 
    } 

    protected override object GetInstance(Type service, string key) 
    { 
     if (Execute.InDesignMode) 
     { 
      return base.GetInstance(service, key); 
     } 

     return string.IsNullOrWhiteSpace(key) 
        ? this.container.Resolve(service) 
        : this.container.ResolveNamed(key, service); 
    } 

    protected override IEnumerable<object> GetAllInstances(Type service) 
    { 
     return Execute.InDesignMode 
        ? base.GetAllInstances(service) 
        : this.container.Resolve(typeof(IEnumerable<>).MakeGenericType(service)) as IEnumerable<object>; 
    } 

    protected override void BuildUp(object instance) 
    { 
     if (Execute.InDesignMode) 
     { 
      base.BuildUp(instance); 
     } 
     else 
     { 
      this.container.InjectProperties(instance); 
     } 
    } 

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

    protected override IEnumerable<Assembly> SelectAssemblies() 
    { 
     foreach (var assembly in base.SelectAssemblies()) 
     { 
      yield return assembly; 
     } 

     yield return Assembly.GetEntryAssembly(); 
     yield return typeof(TViewModel).Assembly; 
    } 

    // other methods are only executed at runtime/not design time relevant 
} 

编辑2:解决了!需要将DesignTime View程序集添加到Boostrapper的SelectAssemblies方法。引导程序和视图不在同一个程序集中(在我的情况下)。

protected override IEnumerable<Assembly> SelectAssemblies() 
    { 
     foreach (var assembly in base.SelectAssemblies()) 
     { 
      yield return assembly; 
     } 

     yield return typeof(MyDesignTimeView).Assembly; // !!!IMPORTANT!!! 
     yield return Assembly.GetEntryAssembly(); 
     yield return typeof(TViewModel).Assembly; 
    } 
+1

你使用什么容器? – mvermef

+1

看着你发布的内容,并回答我以前的帖子和引导程序是最佳答案的理想信息 – mvermef

+0

@mvermef Autofac,但引导程序在应用程序程序集中。 window/usercontrols和viewmoddels在一个单独的程序集中。所以我假设caliburn应该使用默认引导程序 – Beachwalker

做您使用SelectedAssemblies的覆盖,这是卡利如何找到其他项目,如视图/的ViewModels您需要,无论是引用的程序集,特别是如果你正在使用MEF作为容器。 -