Clay and Castle Windsor 2.5 - c#

I've just downloaded the dynamic object framework Clay and am running into issues regarding castle project versions. Clay uses functionality from v2.0 of "castle" whilst I have a project which has been started referencing v2.5. Needless to say just to make matters more interesting I'm a complete beginner in all things "Castle" and IoC.
The real problem is that upgrading the references within clay solution results in a depreciated method warning. Regardless of whether you supress the method or not, the provided unit tests fail with a "Cannot perform runtime binding on a null reference" exception in the following code in "Intercept" of "InterfaceProxyBehavior":
var invoker = BindInvoker(invocation);
invoker(invocation);
The code that produces the run-time warning is in "CreateInstance" of "DefaultClayActivator":
//var proxyType = _builder.CreateClassProxy(baseType, options);
var proxyType = _builder.CreateClassProxyType(baseType, null, options);
As previously stated I'm still a complete beginner with Castle Windsor and just starting out with IoC so haven't even come across the Proxy stuff yet. Frustratingly I have no idea what the error message is even telling me, or asking for.
Have anyone already ported Clay across to version 2.5 of the castle project, so know the steps needed. Or can any one with experience of this part of castle throw anymore light on the error and what I may need to do to resolve it.
Updated
I'm still not really any the wiser as to the functionality that is failing, but have had chance to revisit the code running it both with v2.0 (works) and v2.5 (breaks) in castle.core. Attached are two images of the debug information when it works and then when it breaks. The test that it fails on is below, I've indicated the call with a comment.
namespace ClaySharp.Tests {
[TestFixture]
public class BinderFallbackTests {
...
[Test]
public void TestInvokePaths() {
var dynamically = ClayActivator.CreateInstance<Alpha>(new IClayBehavior[] {
new InterfaceProxyBehavior(),
new AlphaBehavior()
});
Alpha statically = dynamically;
IAlpha interfacially = dynamically;
Assert.That(dynamically.Hello(), Is.EqualTo("World-"));
Assert.That(statically.Hello(), Is.EqualTo("World-"));
Assert.That(interfacially.Hello(), Is.EqualTo("World-")); // <- Fails on this call
Assert.That(dynamically.Foo(), Is.EqualTo("Bar-"));
Assert.That(interfacially.Foo(), Is.EqualTo("Bar-"));
Assert.Throws<RuntimeBinderException>(() => dynamically.MissingNotHandled());
}
...
}
}
This is the debug information when using v2.5 of castle.core and the exception is thrown:
This is the debug information using v2.0 of castle.core (which works) for the same call / line that causes the problem with v2.5

It seems I fixed this. (all tests passing)
See the workitem on codeplex I created and the changes I pushed to my fork:
http://clay.codeplex.com/SourceControl/network/Forks/remcoros/Clay

I have never used this Clay thing, so all stuff below is based on assumptions.
The error message from BindInvoker is not a Castle error, but I'm guessing it's happening because the invoker is trying to bind to invocation target of the proxy which in DynamicProxy 2.1 used to have a value in some cases, which was wrong, and later versions 2.2 and 2.5 fixed that but it was a breaking change that you're now experiencing.
The other error message is telling you
Use CreateClassProxyType method
instead.
Which is the other method you commented out. What's not obvious here?

Some nice tutorials on Clay dynamic objects:
Malleable C# dynamic objects Part 1 Link
Malleable C# dynamic objects Part 2 Link.

Related

XmlSerializer behaves different with a property's private getter on .net framework and .net core

I've consumed a third party nuget package which supported .net core and .net framework (.net standard).
My project was a .net framework 4.62 project and when I've used that third party, I've received an exception from the XmlSerializer.
The problem was due to a private getter in a property.
Only public properties and fields can be serialized. Properties must have public accessors (get and set methods). If you need to serialize non-public data, use the BinaryFormatter class rather than XML serialization.
Full Source
After receiving that error, I tried to open a .net core 2.2 project, consumed the same third party nuget and saw that the same code worked there.
He is a small example of code that reproduces the issue:
public class Test
{
public string TestProp { private get; set; }
}
// Exception on .net 462 and works on .net core 2.2
var serializer = XmlSerializer.FromTypes(new[] { typeof(Test) });
So, is this a bug on the .net core implementation or a feature?
Is there anything I can do rather to support this on .net framework without forking the repo and fixing the code?
The "bug" here is that it fails at a different time; on net462 it fails during FromTypes; on netcoreapp2.2 and netcoreapp3.0, it fails during the Serialize, with:
System.InvalidOperationException: There was an error generating the XML document.
---> System.MethodAccessException: Attempt by method 'Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterTest.Write2_Test(System.String, System.String, Test, Boolean, Boolean)' to access method 'Test.get_TestProp()' failed
So ... it really isn't worth worrying about, IMO. There is no real feature difference, by which I mean: it isn't going to work either way. So just... don't do that?
But: you could log it as a bug on github, and even submit a PR so that it fails earlier, if you really want.
That said: if you add:
public bool ShouldSerializeTestProp() => false;
then it will actually work on netcoreapp2.2 and netcoreapp3.0, which is... nice I guess? And could even be considered a reason not to change the new behavior.

How to Register a Service in Mac OS?

I am experimenting with Mono, MonoMac, and C#. I try to write a simple application based on a service for Mac OS. I followed Apple's developer documentation on implementation of service providers.
My problem is: how to register a service. In Objective-C I would call the setServicesProvider method of NSApplication. But it seems that there is no such a method in MonoMac. Is this right? In the mono docs I found that NSApplication is supposed to have a services provider with a corresponding setter. But calling the SetServicesProvider like:
MyClass myClass = new MyClass();
NSApplication.SetServicesProvider(myClass);
results in the following error:
Error CS0117: `MonoMac.AppKit.NSApplication' does not contain a definition for `SetServicesProvider' (CS0117)
What is the problem here? Is the ServicesProvider property part of the 10% of AppKit that is not implemented so far (The Status section on the MonoMac project page says under "AppKit (About 10% left to be done))?
Alternatively, I tried to find a class NSRegisterServicesProvider as suggested in the apple developer's example. But I cannot find such a class.
Anyone knows how to register a service using MonoMac? Could you please point me to a solution, an example?
I am using MonoDevelop 3.1.1 and Xamarin.Mac development add-in (Version 3.1.1). The latter is at least what is stated in the add-in manager. The version information tab in the "About MonoDevelop" says "Xamarin.Mac: Not Installed". But I think the latter is not right since I get for example access to the NSApplication class using MonoMac.AppKit.
I asked this question on the Mono - OSX mailing list but unfortunately I did get no reply so far.
This is wrapped by a property in Xamarin.Mac. Try;
NSApplication.SharedApplication.ServicesProvider = new myClass()
The hardest thing I have found with these services is getting the info.plist declaration correct.

How to easily tell if Ninject can resolve a class

I'm introducing Ninject into a large mess of a existing project. I want to write a diagnostic test to make sure that all of the classes Ninject will end up creating can actually BE resolved by Ninject...without actually creating any of them.
The reason I want to avoid the actual construction is that many of these classes have a tendency to start up database operations in their constructors (sigh yes I know). Otherwise I would just run them all through Get<T> with a try/catch
There's a CanResolve extension on IResolutionRoot (i.e., you can use it against Kernel if you have the right usings in place). There's a CreateRequest that you use to create the request. Have a look in the sources and tests if you need an example or any deeper information.
I know this is an old post but it was the first one I found when searching for how to find if a class can be resolved by Ninject without actually calling get() and risking an exception.
Ninject version 3.0.2 have a method CanResolve which returns a boolean:
kernel.CanResolve<T>()
I got 3.0.2 from nuget but its currently market unstable (Ninject.3.0.2-unstable-9037) so I'm not sure if I use this in production just yet.

Why do I suddenly get an exception when using the System.Reflection.Assembly.CodeBase property?

In the fragment below, the CodeBase property fails on the assembly System.Xml.Xsl.CompiledQuery, no where else. The message says that "The invoked member is not supported in a dynamic assembly".
I get that the CodeBase property is not implemented, what I don't get is why all of a sudden this is a problem. This code has been in service for months without a problem and suddenly ...
if( CompareCaseInsensitive( Path.GetFileNameWithoutExtension( assembly.CodeBase ), namespaceURI ) )
return assembly;
I have several options available to code around this, but I'm hoping that someone can explain what happened in a way that might lead to a more robust solution.
Edited with a follow on question.
Is there some way to tell which assemblies have this property implemented and which do not without resorting to exceptions?
Any code that's generated with System.Reflection.Emit namespace classes won't have a CodeBase. Since the code wasn't loaded from an assembly, it was generated at runtime. That certainly includes System.Xml.Xsl classes, they do use the internal System.Xml.Xsl.XmlILGenerator class which heavily leans on System.Xml.Xsl.IlGen. Lots of Reflection.Emit code there.
I cannot guess why this worked before. Maybe .NET 4.0, not sure.

Did the Unity Team fix that "generics handling" bug back in 2008?

At my level of experience with Unity it might be faster to ask whether the "generics handling" bug acknowledged by ctavares back in 2008 was fixed in a public release.
Here was the problem (which might be my problem today):
Hi,
I get an exception when using ....
container.RegisterType(typeof(IDictionary<,>),
typeof(Dictionary<,>));
The exception is...
"Resolution of the dependency failed,
type = \"IDictionary2\", name = \"\".
Exception message is: The current
build operation (build key Build
Key[System.Collections.Generic.Dictionary2[System.String,System.String],
null]) failed: The current build
operation (build key Build
Key[System.Collections.Generic.Dictionary2[System.String,System.String],
null]) failed: The type Dictionary2
has multiple constructors of length
2. Unable to disambiguate.
When I attempt...
IDictionary
myExampleDictionary =
container.Resolve>();
Here was the moderated response:
There are no books that'll help, Unity is a little too new for publishers to have caught up yet.
Unfortunately, you've run into a bug in our generics handling. This is currently fixed in our internal version, but it'll be a little while before we can get the bits out. In the meantime, as a workaround you could do something like this instead:
public class WorkaroundDictionary : Dictionary
{
public WorkaroundDictionary() { }
}
container.RegisterType(typeof(IDictionary<,>),typeof(WorkaroundDictionary<,>));
The WorkaroundDictionary only has the default constructor so it'll inject no problem. Since the rest of your app is written in terms of IDictionary, when we get the fixed version done you can just replace the registration with the real Dictionary class, throw out the workaround, and everything will still just work.
Sorry about the bug, it'll be fixed soon!
According to the Unity Team:
Just wanted to let folks know we've
released the bits that have the
generics fixes in them. Take a look
and let us know what you think. It's
checked into codeplex source control.
You may need to get the latest source and build yourself (2.x) as the bug fix may not have been packaged yet.

Categories

Resources