Xaml error when referencing internal classes in strongly-named assembly - c#

I have a peculiar problem regarding internal classes used from xaml.
The problem is as follows:
We decided to strong-name all our assemblies. After the strong-naming, all but one project compiles without a hitch under VS 2017. The situation is as follows:
Assembly Company.Component - Compiles without problems, and exposes its internals as follows:
[assembly: InternalsVisibleTo("Company.Component.Test, PublicKey={omitted}")]
[assembly: InternalsVisibleTo("Company.OtherLibrary, PublicKey={omitted}")]
Assembly Company.Component.Test - Compiles without problems, and can access internals in Company.Component just fine. All tests pass.
Company.OtherLibrary - Does not compile at all, due to the following error in one of its xaml files:
Only public or internal classes can be used within markup. 'Converter1' is not public or internal.
The xaml file in question can be seen below (with names changed):
<ns:class x:Class="Company.OtherLibrary.Class"
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"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:converters="clr-namespace:Company.Component.Converters;assembly=Company.Component"
xmlns:viewModels="clr-namespace:Company.OtherLibrary.ViewModels"
xmlns:ns="clr-namespace:Company.Component;assembly=Company.Component"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
d:DataContext="{d:DesignInstance d:Type=viewModels:ViewModelClass}"
Style="{StaticResource {x:Type ns:Style}}">
<UserControl.Template>
<ControlTemplate>
<DockPanel>
<DockPanel.Resources>
<converters:Converter1 x:Key="Converter1" />
<converters:Converter2 x:Key="Converter2" />
<converters:Converter3 x:Key="Converter3" />
<converters:Converter4 x:Key="Converter4" />
</DockPanel.Resources>
...
</DockPanel>
</ControlTemplate>
</UserControl.Template>
Now to answer some questions:
The public key is the correct public key (not only the token) of the OtherLibrary assembly. It is in fact the same one used for the test assembly.
The assembly name for OtherLibrary is the same as the one in its properties.
The code worked before the strong naming. No changes have been made to any code file in the projects (bar AssemblyInfo.cs). I have checked with VS 2017 git compare. The edited lines are the ones shown, and the edit is to insert public keys.
The xaml-namespaces can sometimes be found, and sometimes not. This only goes for the namespaces that have no public classes.
All converters seen in the dock panel resources are internals in the Company.Component assembly. They all give the following error:
The type '{type}' is not accessible.
All libraries are built against the same version of the framework/dlls.
The assembly reference to Company.Component have 'copy local' set to true.
What I've tried
Clearing xaml shadow-cache
Cleaning and rebuilding.
Changing active build-configuration (both platform and Debug/Release).
Manually cleaning all bin and obj directories for all projects.
Restarted both computer and VS 2017.
All of the above at once.
There is something very simple that I've obviously overlooked. Can someone please help me figure out what is going on here? I am not allowed (for reasons left out) to change the component library other than strongly naming it.

Related

MC3050 - DataProtectionScope not found in System.Security.Cryptography in XAML

I'm designing a small encoding/decoding application that uses System.Configuration.Cryptography.ProtectedData methods at its core.
To let the user select the data protection scope, I've included radio buttons such as this one:
<RadioButton x:Name="rbtMachineScope"
GroupName="rbgProtectionScope"
IsChecked="{Binding Path=ProtectionScope, Converter={StaticResource EnumToBoolean}, ConverterParameter={x:Static crypto:DataProtectionScope.LocalMachine}}"
Content="_Machine"/>
Obviously, the XAML file begins like this:
<Window x:Class="DecodeEncodeApp.MainWindow"
xmlns:crypto="clr-namespace:System.Security.Cryptography;assembly=System.Core"
DataContext="{Binding Path=EncryptionModule}">
<Window.Resources>
<!-- Converters -->
<conv:EnumToBooleanConversion x:Key="EnumToBoolean" />
</Window.Resources>
(edited for brevity)
EncryptionModule is an object of the type TextEncryption:
public class TextEncryption : INotifyPropertyChanged
{
public DataProtectionScope ProtectionScope;
}
(In the interest of saving more space, trust me that ProtectionScope comes with a private field that is duly used in its get and set methods in such a way that bindings are possible. I've checked that.)
(Also, that EnumToBooleanConversion implements IValueConverter quite banally.)
Compiling gets the following message:
"Unknown build error, MC3050: type 'DataProtectionScope' not found." (Translated back from the local French, sorry if inaccurate.)
Except that in TextEncryption (that has using System.Security.Cryptography;), DataProtectionScope is found.
I use VS2019 and my project uses .Net 5.0.
What did I do wrong?

I decompiled a dotnet .dll with ILSpy but the xaml files have some issues

I decompiled a .dll with ILSpy and the code looks fine but I have a xaml file which is:
<Window x:Class="PrinterManager.ShellView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:PrinterManager" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="Printer Manager" Height="450" Width="400" ResizeMode="NoResize" Icon="C:\Program Files (x86)\CENSURED" WindowState="Minimized" ShowInTaskbar="False" Visibility="Hidden">
.....MORE XAML STUFF....
<Style x:Key="btnStyle" TargetType="{x:Type Button}">
....MORE XAML....
And I have a bunch of errors:
Severity Code Description Project Path File Line Suppression State
Error CS0102 The type 'ShellView' already contains a definition for '_contentLoaded' PrinterManager C:\Users\PietroConvalle\Documents\DotNetDecompileThingy\source\PrinterManager\obj\Debug\net5.0-windows C:\Users\PietroConvalle\Documents\DotNetDecompileThingy\source\PrinterManager\obj\Debug\net5.0-windows\shellview.g.cs 44 Active
Error CS0111 Type 'ShellView' already defines a member called 'InitializeComponent' with the same parameter types PrinterManager C:\Users\PietroConvalle\Documents\DotNetDecompileThingy\source\PrinterManager\obj\Debug\net5.0-windows C:\Users\PietroConvalle\Documents\DotNetDecompileThingy\source\PrinterManager\obj\Debug\net5.0-windows\shellview.g.cs 51 Active
Error CS0111 Type 'ShellView' already defines a member called 'System.Windows.Markup.IComponentConnector.Connect' with the same parameter types PrinterManager C:\Users\PietroConvalle\Documents\DotNetDecompileThingy\source\PrinterManager\obj\Debug\net5.0-windows C:\Users\PietroConvalle\Documents\DotNetDecompileThingy\source\PrinterManager\obj\Debug\net5.0-windows\shellview.g.cs 71 Active
And many more
But if I just remove x:Class="PrinterManager.ShellView" the errors are gone and it builds and runs fine.
I'm sure it's a trivial fix but I never coded in C#, I suspect that's some dependency or config issue?
Sorry can't share the full source for copyright reasons but happy to share a few extra bits if it helps.
Exported with latest ILSpy stable, c# 10.0 / VS 2022
UPDATE: this seems like my issue https://stackoverflow.com/a/25849873/8340761 but I'm not sure what I'm supposed to change?
To fix it I just had to move each .xaml file next to the same file name .cs
This issue was actually fixed in ILSpy 8

Adding a resource to WPF application causes build error

I'm working through the book Head First C# and consistently have issues when adding resources to a window. This is a 100% repeatable error on any new WPF application I create when adding a new resource. The only way around this is to comment out the resource, build, and uncomment, as detailed in MVCE below. Images are included as proof this isn't a what-if or theoretical scenario.
What are the proper steps to add a resource file and use it within a WPF project?
I'm using Visual Studio Community 2017: Version 15.9.9
Target framework: .NET Framework 4.6.1
MVCE:
Create a new WPF application. Add a class:
//MyDataClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XAMLBuildErrorExample
{
class MyDataClass
{
public string Foo { get; set; }
}
}
Within MainWindow.xaml add a resource
<Window x:Class="XAMLBuildErrorExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:XAMLBuildErrorExample"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:MyDataClass x:Key="exampleResource" />
</Window.Resources>
<Grid>
</Grid>
</Window>
Attempt to build. Error "The tag 'MyDataClass' does not exist in XML namespace 'clr-namespace:XAMLBuildErrorExample'. Line 11 Position 10.":
Comment out the resource. Build succeeds:
Uncomment resource. Build succeeds whereas it failed before:
Any subsequent cleaning of the solution makes building impossible because of the error in the first image.
It appears the problem is tied to initial computer.
Tested on another work station VS Community 2017 version 15.9.11 and build was successful without any issues. Build>Clean>Build without issues.

Setting the Name-attriubute on a custom control results in compilation error

I have a very simple wpf custom control that defines two constructors:
public class SomeControl : System.Windows.Controls.Button
{
public SomeControl()
{
}
public SomeControl(ISomeService service)
{
}
}
This control is defined in a class library called ControlLib. The ISomeService interface is defined in another class library project called ServiceContracts and ControlLib has a reference to it.
The third project in the solution (called FrontEnd) is a simple WPF-project and i place the custom control on the MainWindow like this:
<Window x:Class="FrontEnd.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:ControlLib;assembly=ControlLib"
Height="450"
Width="800">
<Grid>
<controls:SomeControl />
</Grid>
Until now, everything works fine and as intended. The project structure looks roughly like this:
The problem occurs when i give the costum control a name. When i set the Name attribute like this <controls:SomeControl x:Name="OhWhy" /> the project does not longer compile. I get the following error:
Unknown build error, 'Cannot resolve dependency to assembly 'ServiceContracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event. Line 8 Position 31.' FrontEnd C:\01_Data\Tmp\SomeSolution\FrontEnd\MainWindow.xaml 8
My question is: Why does it break when i add the Name-attribute and why does it work in the first place?
I know that setting the Name-attribute will add a field to the designer generated *.g.i.cs file to access the control from code behind, but compilation also breaks when i do the same in a template in some resource dictionary without any designer generated files.
The following things solved the problem but im not exactly sure why:
Adding a reference in FrontEnd to ServiceContracts
Making the parametrized constructor internal
This is caused by the XAML compiler. Please refer to the following question for more information.
Cannot resolve dependency to assembly 'PostSharp' because it has not been preloaded
The solution is to add a reference to ServiceContracts.dll from the WPF application project.
I think what is happening with giving it a name is that you get a local member variable of type SomeControl in FrontEnd. This pulls in the dependency. Before that, you just have baml in a resource and when the baml is deserialized at runtime, the SomeControl type is already loaded in the AddDomain and can be dynamically instantiated using reflection.

WPF and Workflow foundation don't work together

I have really strange problem. I've created WPF project in 2012 or 2013 VS it doesn't matter. I use .NET 4.5.
I add a new Activity (Workflow class) to that project. Its name is CustomActivity.
Then I add a new class that has got an attached property, example below:
public class AttachedObject : DependencyObject
{
public static readonly DependencyProperty NameProperty = DependencyProperty.RegisterAttached(
"Name",
typeof(string),
typeof(AttachedObject),
new FrameworkPropertyMetadata(
string.Empty,frameworkPropertyMetadataOptions.AffectsRender));
public static void SetName(ContentControl element, string value)
{
element.SetValue(NameProperty, value);
}
public static string GetName(ContentControl element)
{
return (string)element.GetValue(NameProperty);
}
}
The last step is to change MainWindow class that way:
public MainWindow()
{
InitializeComponent();
var activity = new CustomActivity();
}
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1;assembly=WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ContentControl wpfApplication1:AttachedObject.Name="MainArea"/>
</Grid>
</Window>
The problem is it doesn't compile because of below error:
Error 1 The type or namespace name 'CustomActivity' could not be found (are you missing a using directive or an assembly reference?) WpfApplication1\MainWindow.xaml.cs 13 32 WpfApplication1
CustomActivity has a default namespace. In obj folder there is CustomActivity.g.cs generated, so I have no idea what's going on.
It's 100% reproducible. When I remove using of CustomActivity or using of AttachedObject from xaml then the problem disappear.
Try replacing this:
xmlns:wpfApplication1="clr-namespace:WpfApplication1;assembly=WpfApplication1"
with this
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
The error you're seeing is due to a "known" issue in WPF applications that xaml namespaces that reference clr namespace from current assembly your in don't require the full assembly qualified name. If you were to declare a xaml namespace that references a clr namespace from another assembly, than you would have to specify the full name (with the ;[assemblyname] syntax).
Workflow Foundation has nothing to do with it.
EDIT:
Didn't realize it was a xaml activity.
But still, you can make it work, maybe, with a few hacks, but I wouldn't recommend it.
The reason you get that error is due to the different code generation and build action VS uses when creating xaml artifacts for WPF (Page):
System.Windows.Application.LoadComponent(this, resourceLocater);
and when creating xaml activities (XamlAppDef):
typeof(CustomActivity).Assembly.GetManifestResourceStream(resourceName);
If you turn your CustomActivity xaml build action to Page, the whole thing will compile - but i'm guessing something else might be broken someplace else...or not, who knows. My guess is that these two kinds of xaml were not meant to live together in a VS WPF application project template. But you can still define activities in a WF activity library, that way your activities will also be more easily reusable for other projects, WPF, console or even services.
I have the same issue under Visual Studio 2017.
The problem in my case is that Visual Studio is not compiling the Workflow activities before the code that use them.
To fix it, what I did is to move all workflows to other project dll, so visual Studio is forced to compile the workflows before the classes that make use of them.

Categories