Portable Class Library ICommand compilation error in WPF — Not sure how to resolve this appropriately?

北城余情 提交于 2019-11-30 21:29:38

You must add a reference to assembly 'System.Windows, Version=2.0.5.0

The advice is excellent, the message is not that great. Clearly you got baffled by the version number. Right-click your WPF project, Add Reference and tick System.Windows. Which solves your problem.

The missing magic is this line in the System.Windows.dll reference assembly:

  [assembly: TypeForwardedTo(typeof(ICommand))]

Which gets ICommand forward from System.Windows.dll to System.dll

Keep in mind that System.Windows.dll from the c:\program files (x86)\reference assemblies subdirectory is just a reference assembly. It doesn't contain any code or types at all, just [TypeForwardedTo] attributes. It acts as an "adapter", bridging the gap between different .NET framework platforms. The final executable doesn't actually have a dependency on System.Windows.dll at all.

This is not exactly a bug, it is more about what's included in the .NET Portable Subset. MSBuild is correct in complaining.

If you look at the manifest of PortableClassLibrary, you will see that an extern reference to System.Windows is actually made.

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

And if you check what is actually contained in .NETPortable, you'll find that the included System assembly is v2.0.5.0

You can find it here -> C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\Profile158\

...as is System.Windows at v2.0.5.0

So technically speaking, MSBuild is correct in asking for System.Windows, since this is not included explicitly in a build for WPF.

Although the TypeForwarding argument is interesting, it would still be moot, since at v2.0.5.0, there was no type forwarding to be done.

Now, if you actually look at System.Windows v4.0.0.0, there IS a TypeForwardedTo rule for ICommand (use reflector)

So the question here is more of a design issue, more than anything. System.Windows conflicts with WPF, yet this is only due to the other implementation of Window.

So to fix this, reference the v2.0.5.0 System.Windows in C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.0\Profile\Profile158\System.Windows.dll (I would take a copy of it for this project).

Your last step is to resolve the type ambiguity that occurs because of this... you'll get a type ambiguity between System v4.0.0.0 and System.Windows v2.0.5.0 for the use of ICommand

You can solve this by removing System.Windows from the 'global' alias (hit F4 on the reference), and add in a custom alias, ex. SomeAlias

Then just reference it via it's alias.

extern alias SomeAlias;

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

Voila.. this was really interesting, so I've detailed it a bit more here, where I could include screenshots (and talk about the ReSharper hiccup)

are you referencing System.dll?

ICommand

Supported in: Portable Class Library

No need to reference System.Windows.dll in your PCL, just add it in the WPF project.

Test solution

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!