我在尝试验证容器时遇到错误。
配置无效。为类型创建实例 SettingModel失败。已注册的类型为SettingModel的委托 抛出一个例外。无效的URI:指定的端口无效。
它似乎是由ThemeManager
引起的,它属于mahapps.metro dll我似乎无法与Simple Injector很好地配合。
public SettingModel()
{
ThemeColor = ThemeManager.AppThemes.Select(t => t.Name).ToList();
AccentColor = ThemeManager.Accents.Select(a => a.Name).ToList();
var currentSetting = ThemeManager.DetectAppStyle(Application.Current);
CurrentTheme = currentSetting.Item1.Name;
CurrentAccent = currentSetting.Item2.Name;
}
我慢慢地删除了东西,它已经到了我使用主题管理器的每个地方它都打破了。所以我开始取出碎片,直到我在编译时不断得到xamlparseexception,这很奇怪,因为我的代码在放入简单的进样器之前就已经编译了。
我遵循WPF集成教程,除非它已过时。我真的想尝试简单的喷油器,但它没有很好地集成。
更新:完全例外
System.InvalidOperationException was unhandled
HResult=-2146233079
Message=The configuration is invalid. Creating the instance for type MainWindow failed. The registered delegate for type MainWindow threw an exception. Invalid URI: Invalid port specified.
Source=SimpleInjector
StackTrace:
at SimpleInjector.InstanceProducer.VerifyInstanceCreation()
at SimpleInjector.Container.VerifyInstanceCreation(InstanceProducer[] producersToVerify)
at SimpleInjector.Container.VerifyThatAllRootObjectsCanBeCreated()
at SimpleInjector.Container.VerifyInternal()
at SimpleInjector.Container.Verify(VerificationOption option)
at SimpleInjector.Container.Verify()
at Program.Bootstrap() in c:\Users\Work\Documents\Visual Studio 2012\Projects\AzurePeek\AzurePeek\Program.cs:line 35
at Program.Main() in c:\Users\Work\Documents\Visual Studio 2012\Projects\AzurePeek\AzurePeek\Program.cs:line 14
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: SimpleInjector.ActivationException
HResult=-2146233088
Message=The registered delegate for type MainWindow threw an exception. Invalid URI: Invalid port specified.
Source=SimpleInjector
StackTrace:
at SimpleInjector.InstanceProducer.GetInstance()
at SimpleInjector.InstanceProducer.VerifyInstanceCreation()
InnerException: System.UriFormatException
HResult=-2146233033
Message=Invalid URI: Invalid port specified.
Source=System
StackTrace:
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString)
at MahApps.Metro.ThemeManager.get_AppThemes()
at AzurePeek.M
odel.SettingModel..ctor() in c:\Users\Work\Documents\Visual Studio 2012\Projects\AzurePeek\AzurePeek\Model\SettingModel.cs:line 24
at lambda_method(Closure )
at SimpleInjector.InstanceProducer.GetInstance()
InnerException:
答案 0 :(得分:4)
<强>更新强>
与@ punker76(MahApps.Metro库的合作者之一)讨论后,我们得出结论,发生此异常是因为您在WPF应用程序范围之外运行该代码。很可能是因为您在单元测试中测试了配置。
你可以在这做两件事。您需要欺骗测试套件以将其作为WPF应用程序运行,或者您必须将MyApps
的代码移出SettingModel
的构造函数。
正如@ punker76所讨论的那样,在启动WPF应用程序时,对new FrameworkElement()
的调用会以某种方式确保内部UriParser
能够解析pack://
uris(谈论奇怪隐藏的丑陋可怕依赖关系)。
另一个选择是我的偏好,就是制作constructor's simple and resilient to failure。这意味着任何与构建对象图无关的代码都应该移出构造函数,并且应该在运行时完成。
有很多方法可以做到这一点,但一种简单的方法是通过推迟SettingsModel
属性的初始化或推迟创建SettingsModel
本身,因为它没有看起来像是一个应该由你的DI容器维护的服务。
通过引入一个允许在运行时访问设置的抽象来推迟创建SettingsModel
:
public interface ISettingsProvider {
SettingsModel CurrentSettings { get; }
}
通过以下实施:
public class SettingsProvider : ISettingsProvider {
private readonly Lazy<SettingsModel> model = new Lazy<SettingsModel>(
() => new SettingsModel());
public SettingsModel CurrentSettings {
get { return this.model.Value; }
}
}
这可以注册如下:
container.RegisterSingle<ISettingsProvider>(new SettingsProvider());
原始回答
问题不太可能由Simple Injector引起。 Simple Injector的Verify()
方法没有什么特别之处。如果您将Verify()
的来电替换为new SettingModel();
,则很可能会看到相同的异常。
事实上,如果你查看MahApps.Metro.ThemeManager.AppThemes
属性的the source code,你会看到以下代码:
var themes = new[] { "BaseLight", "BaseDark" };
_appThemes = new List<AppTheme>(themes.Length);
foreach (var color in themes)
{
var appTheme = new AppTheme(color, new Uri(string.Format("pack://application:,,,/MahApps.Metro;component/Styles/Accents/{0}.xaml", color)));
_appThemes.Add(appTheme);
}
return _appThemes;
如果查看提供给Uri
构造函数的url,您就可以理解为什么它会抛出“无效的URI:指定的无效端口”异常。如果在控制台应用程序中运行以下代码,则会出现相同的错误:
new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml");
所以我必须得出结论,MahApps.Metro.ThemeManager.AppThemes
属性中存在导致此问题的错误。我想知道你以前是如何设法让这个工作的,因为我没有办法解决这个bug。您是否曾在介绍Simple Injector的同时升级到较新版本的MahApps.Metro?