WPF中的可移植类库ICommand编译错误 - 不确定如何正确解决此问题?

时间:2013-12-09 18:41:34

标签: c# .net wpf visual-studio-2013 portable-class-library

一些背景资料:

  • 我正在使用VS 2013
  • 我创建了一个可移植类库(目标:.NET 4.5 / Silverlight 5 / Win Phone 8 / Win Store 8)
  • 我在名为ICommand的类中实现了MyCommand接口。

MyCommand.cs:

public class MyCommand : ICommand
{
    public bool CanExecute(object parameter)
    {
        throw new NotImplementedException();
    }

    public void Execute(object parameter)
    {
        throw new NotImplementedException();
    }

    public event EventHandler CanExecuteChanged;
}

我发现当我尝试引用WPF 4.5应用程序中的MyCommand类时,我收到以下错误:

  

类型'System.Windows.Input.ICommand'在程序集中定义   没有引用。您必须添加对程序集的引用   'System.Windows,Version = 2.0.5.0,Culture = neutral,   PublicKeyToken = 7cec85d7bea7798e,Retargetable = Yes'。

我不确定为什么这种情况正在发生,或者我能做些什么来适当地解决它。在搜索完互联网后,我发现答案是在我的WPF应用程序中添加对System.Windows.dll 4.0.0.0的引用。这样做允许我编译和运行应用程序,但我的IDE抱怨:

  

接口成员'无效   System.Windows.Markup.IComponentConnector.Connect(in,object)'不是   实现。

对于我的MainWindow.cs类,会发生这种情况。有没有更好的解决办法,只是处理这个错误,所以我不是在WPF应用程序中添加System.Windows.dll的引用,它真的不需要它?而且我说它并不真的需要它,因为如果我将MyCommand类复制/粘贴到Wpf应用程序中它可以正常工作。它只有一个问题,因为我试图将它用作便携式类库。


更新:

似乎除此之外还有更多的东西。我创建了一个新的Wpf应用程序并使用NuGet来引用MvvmCross解决方案(因为它有一个MvxCommand对象)。当我这样做时,我得到同样的错误。

大卫·基恩answer对类似的问题表明,这应该通过VS2012 / VS2013修复,如果没有,只需重新安装/修复。我完全删除了我的VS安装并从头开始重新安装(VS2013),但仍有此问题。那么,这真的是一个错误,还是我做错了什么?


更新2:

我试图查看是否可以将MyCommand类的实例分配给ICommandICommand cmd = new MyCommand();并收到以下错误:

  

无法将类型'PortableClassLibrary1.MyCommand'隐式转换为   'System.Windows.Input.ICommand'。存在显式转换(是   你错过了一个演员?)

出于某种原因,PCL似乎没有为我的桌面应用程序输入System.Windows.dll [2.0.5.0] ICommand到System.dll [4.0.0.0] ICommand ...呃!


更新3:

我上传了my solution,以便更清楚地了解问题所在。


更新4:

我在这个问题上打开了Microsoft connect ticket


更新5:

在对这不起作用感到沮丧之后平静下来...而其他人告诉我他们没有得到相同的“界面”错误。我意识到添加System.Windows.dll的“副作用”是ReSharper 8.1错误。我想是时候向ReSharper而不是微软抱怨了。 叹息

3 个答案:

答案 0 :(得分:6)

  

您必须添加对程序集'System.Windows,Version = 2.0.5.0

的引用

建议很好,信息不是很好。很显然,你对版本号感到困惑。右键单击WPF项目,添加引用并勾选System.Windows。这解决了你的问题。

缺少的魔法是System.Windows.dll引用程序集中的这一行:

  [assembly: TypeForwardedTo(typeof(ICommand))]

将ICommand从System.Windows.dll转发到System.dll

请记住,c:\ program files(x86)\ reference assemblies子目录中的System.Windows.dll只是 引用程序集。它根本不包含任何代码或类型,只包含[TypeForwardedTo]属性。它充当“适配器”,弥合了不同.NET框架平台之间的差距。最终的可执行文件实际上根本不依赖于System.Windows.dll。

答案 1 :(得分:1)

这不是一个错误,它更多的是关于.NET Portable Subset中包含的内容。 MSBuild在抱怨方面是正确的。

如果你看看PortableClassLibrary的清单,你会看到实际上是对System.Windows的一个extern引用。

.assembly extern retargetable System.Windows
{
  .publickeytoken = (7C EC 85 D7 BE A7 79 8E )                         // |.....y.
  .ver 2:0:5:0
}

如果你检查.NETPortable中实际包含的内容,你会发现所包含的系统程序集是v2.0.5.0

你可以在这里找到它 - > C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\Profile158\

...与V2.0.5.0中的System.Windows一样

从技术上讲,MSBuild在请求System.Windows时是正确的,因为在WPF的构建中没有明确包含它。

尽管TypeForwarding参数很有意思,但它仍然没有实际意义,因为在v2.0.5.0中,没有类型转发要做。

现在,如果您实际查看System.Windows v4.0.0.0,那么ICommand有一个TypeForwardedTo规则(使用反射器)

所以这里的问题更多的是设计问题,而不是任何事情。 System.Windows与WPF冲突,但这只是由于Window的其他实现。

所以要解决这个问题,请参考C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\Profile158\System.Windows.dll中的v2.0.5.0 System.Windows(我会为此项目获取它的副本)。

您的最后一步是解决因此而发生的类型歧义...您将在System v4.0.0.0和System.Windows v2.0.5.0之间获得类型歧义,以便使用ICommand

您可以通过从“全局”别名中删除System.Windows(在引用上按F4)来解决此问题,并添加自定义别名,例如。 SomeAlias

然后通过它的别名引用它。

extern alias SomeAlias;

public partial class MainWindow : Window
{
    private SomeAlias::System.Windows.Input.ICommand _command;
    ...etc...

Voila ..这真的很有趣,所以我详细介绍了here,我可以在其中加入截图(并谈谈ReSharper打嗝)

答案 2 :(得分:0)

你引用了System.dll吗?

的ICommand

  

支持:可移植类库

无需在PCL中引用System.Windows.dll,只需将其添加到WPF项目中即可。

Test solution