I have a really weird problem. The below code works fine if I create a new console app and put the code in but if i create a new console app in my solution and paste exactly the same code in I get a runtime binder exception that the dynamic does not contain a definition for hello. The wierd things is in my existing solution the code never goes into TryGetMember().
This is really bugging me and the solution is too big to move into a new solution and I not convinced that will fix it. In the console application that doesn't work all the reference are the same as in the one that does work. the only difference being it is not in the solution. The whole solution is acting the same way with dynamics - the funny thing is this was working but suddenly stop so i create this simple program to test the theory.
Edit: The application that doesn't work in the solution works fine if I don't attach the debugger i.e. Ctrl+F5.
Any ideas?
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
IDictionary<string, object> dictionary = new Dictionary<string, object>();
dictionary["hello"] = "world";
dynamic d = new MyDynamicModel(dictionary);
var a = d.hello;
}
}
public class MyDynamicModel : DynamicObject
{
private IDictionary<string, object> Values { get; set; }
public MyDynamicModel(IDictionary<string, object> dict)
{
Values = dict;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
return Values.TryGetValue(binder.Name, out result);
}
}
}
It sounds like you have visual studio setup to break on thrown exceptions. Just using Dynamics will throw and handle more exceptions then you think when dealing with C# objects including dynamic objects. The C# binder always tries to do things like call the static version first etc, and then throws a RuntimeBindingException that it can't find the member, handles it, and tries again for the dynamic version.
Under Debug > Exceptions make sure the Thrown isn't checked on RuntimeBinderException or even just all CLR Exceptions.
Related
Following various examples from MS and elsewhere, I have written this piece of test code...
[ComImport]
[Guid("4AEEEC08-7C92-4456-A0D6-1B675C7AC005")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IInitializeWithWindow
{
void Initialize(IntPtr hwnd);
}
and..
private async Task<bool> TestCode()
{
StoreContext Store = StoreContext.GetDefault();
StoreAppLicense licence = await Store.GetAppLicenseAsync();
bool trial = licence.IsTrial;
bool full = licence.IsActive;
IInitializeWithWindow initWindow = (IInitializeWithWindow)(object)Store;
initWindow.Initialize(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle);
StoreProductResult App = await Store.GetStoreProductForCurrentAppAsync();
StoreProduct p = App.Product; // Title, price
string title = p.Title;
StorePrice price = p.Price;
return true;
}
And I call it with using
bool x = TestCode().Result;
It all compiles and runs, so I presumably have all the right usings and references added. But when run, the line:
IInitializeWithWindow initWindow = (IInitializeWithWindow)(object)Store;
stops with the exception..
Unable to cast object of type 'Windows.Services.Store.StoreContext'
to type 'IInitializeWithWindow'
and I have no clue why.
This is a C# program with a UWP wrapper creating an MSIX package.
This seems to be a pretty standard block adapted from various examples from MS.
Within VS 2019, I have associated the program with the store app.
The 'trail' and 'full' variables seem to be populating correctly.
I have called this from various locations, Constructor, random button, etc.
My questions...
Why does the cast throw an exception?
Is this an old way of doing things that no longer applies?
Does associating the package in VS 2019 to the store app make the call to IInitalizeWithWindow redundant?
How do I fix the code so that 'title' and 'price' populate correctly?
Heaps of head bashing and I finally have it working...
Considering that in the last few days there was not a combination/permutation that I did not try, I don't know really the logic of it working now, but anyway..
Within the UWP installer project I associated the project with the App in the Microsoft Store, then I removed the lines:
[ComImport]
[Guid("4AEEEC08-7C92-4456-A0D6-1B675C7AC005")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IInitializeWithWindow
{
void Initialize(IntPtr hwnd);
}
IInitializeWithWindow initWindow = (IInitializeWithWindow)(object)Store;
initWindow.Initialize(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle);
The rest is now working just fine. Funny as I had already associated the app with the store AND removed the offending lines. I must have done something just a little bit different this time!
When repassing a dynamic parameter to a method with params keyword the solution fails to build, I am using .NET 4.6 and VS2015, but the problem also happens with previous versions of .NET Framework. No error is produced on Error List, just a "Build Failed" message at the bottom.
This is the sample code I am trying to run:
public void MethodWithDynamicParameter(dynamic dyn)
{
MethodWithParams(dyn); //This fails to build!
MethodWithParams(new object[] { dyn }); //This compiles!
}
public void MethodWithParams(params object[] objects)
{
}
Can someone explain what is wrong with the first call?
EDIT 1:
I´ve created a new solution with the sample provided by Dave and it builds with no problems. But in my solution the problems persists even after "Close, clean and build". It does not matter if I pass a string, a object, a dynamic or anythin else. At the image below there are no calls to method and the solution still does not build.
I have created a new Console Application using the following code as a test:
class Program
{
static void Main(string[] args)
{
// Test with object:
object x = new object();
MethodWithDynamicParameter(x);
// Test with specific type of object, a string:
MethodWithDynamicParameter("string");
Console.ReadKey();
}
static void MethodWithDynamicParameter(dynamic dyn)
{
MethodWithParams(dyn);
MethodWithParams(new object[] { dyn });
}
static void MethodWithParams(params object[] objects)
{
}
}
For me, the program both compiles and runs without error.
May I suggest the standard "close all documents, clean all, rebuild all" and/or "restart Visual Studio" solutions, if you have not yet attempted this?
Additionally, they dynamic keyword might be the source of your troubles, as it bypasses many of the typing checks until compile time. Try checking your code from where dyn would be declared, prior to making the call to MethodWithDynamicParameter(dynamic dyn).
Here is my code:
using ProtoBuf;
[ProtoContract]
[ProtoInclude(500, typeof(SampleClassDrv))]
public class SampleClass
{
[ProtoMember(1)] public int theInt;
[ProtoMember(2)] public string[] items;
public SampleClass(){}
public SampleClass(int c) {this.theInt = c;}
}
[ProtoContract]
public class SampleClassDrv : SampleClass
{
[ProtoMember(1)] public int theOtherInt;
public SampleClassDrv(){}
public SampleClassDrv(int b):base(1){this.theOtherInt=b;}
}
To compile my DLL I run the following code:
RuntimeTypeModel rModel = TypeModel.Create();
rModel.AllowParseableTypes = true;
rModel.AutoAddMissingTypes = true;
rModel.Add(typeof(SampleClass), true);
rModel.Add(typeof(SampleClassDrv), true);
rModel.Compile("MySerializer", "MySerializer.dll");
Finally I should be able to initialize by RuntimeTypeModel from the dll like so:
MySerializer serializer = new MySerializer();
serializer.Serialize(stream, object);
But Unity throws the following exception
Internal compiler error. See the console log for more information.
[...]
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.
Interestingly enough if I go back and remove the line
[ProtoMember(2)] public string[] items;
It works as expected...
It is also worth noting the RunTimeModel works as expected if used after adding the classes instead of attempting to use dll.
My environment:
Unity3D 4.3.4
Protobuf-net r668
using protbuf-net.dll in Full/unity
I would greatly appreciate if someone could point out the error in my ways.
EDIT
From the suggestion by Flamy I changed form string[] to List
[ProtoMember(2)] public List<string> items;
Sadly the error still persists.
Another Note
Also I decided to use a dll decompiler to see what is going on. I was not able to decompile the dll until the "string[] items" variable was removed.
SOLVED
I think it is related to some issue with compiling the DLL with Unity3D.
When I created the project in Visual Studios with the code I showed above everything seems to be working as expected. Which is a relief as this seems like it would be a huge issue if protobuf could not serialize string[].
I followed the article provided by BCCode to setup the visual studio project and compile the DLLs.
Now all I need to do is create the dll with my large scale project! Fingers Crossed
Thanks everyone for their help!
Are your references correct?
%project dir%\Library\ScriptAssemblies\Assembly-CSharp.dll
Also take a look here:
http://purdyjotut.blogspot.com/2013/10/using-protobuf-in-unity3d.html?m=1
Serilizing array of strings using Binary serilization or a serilization method that uses binary format (protobuff in this case) will always result in so many issues. The reason is String by itself is an array of chars,which doesnt have a defined size, meaning it dont know where one string ends and the next starts... Usually we serialize string array one by one instead of the whole array. so I advice you to to use a property which does that (hopefully protobuff accepts attributes on properties!) or create a list of strings instead (though i haven't tested yet it should work!)
We recently upgraded a very large project from .NET framework 3.5 to 4, and initially everything seemed to work the same. But now bugs have started to appear on copy paste operations.
I have managed to make a small reproducible app, which shows the different behavior in .NET 3.5 and 4.
I have also found a workaround (manually serialize the data to the clipboard), but I'm left with a need to know "why" there is a difference in behavior.
This is the small test app I made:
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
namespace ClipboardTest
{
public class Program
{
[Serializable]
public class Element
{
public Element(string name)
{
this.name = name;
}
public string name;
}
public static List<Element> TestSerializer(List<Element> obj)
{
var memoryStream = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, obj);
return (List<Element>)formatter.Deserialize(new MemoryStream(memoryStream.GetBuffer()));
}
public static List<Element> TestClipboard(List<Element> obj)
{
Clipboard.SetDataObject(obj);
return (List<Element>)Clipboard.GetDataObject().GetData(typeof(List<Element>));
}
public static void DumpObject(string testName, List<Element> obj)
{
if (obj == null)
{
Console.WriteLine("{0} : List is null", testName);
return;
}
foreach (var prop in obj)
{
Console.WriteLine("{0} : {1}", testName, prop.name);
}
}
[STAThread]
static void Main()
{
var copyData = new List<Element> { new Element("all good") };
DumpObject("Serializer", TestSerializer(copyData));
DumpObject("Clipboard", TestClipboard(copyData));
}
}
}
.NET 3.5 output:
Serializer : all good
Clipboard : all good
.NET 4 output:
Serializer : all good
Clipboard : List is null
I have looked at the .NET source for the Clipboard & DataObject class, but I couldn't see what serializer was used. The MSDN documentation says that the type must be serializable, which in this case both the List<> and Element classes are. Copying an Element object works just fine, but as soon as I copy a list of elements, it breaks.
To test, I have created 2 C# "Console Application" projects in Visual Studio 2010 SP1. The first project I have left with the default "Target framework" setting of ".NET Framework 4 Client Profile". The second project I have modified to use ".NET Framework 3.5 Client Profile".
Additional information about my Forms DLL version:
Original filename: System.Windows.Forms.dll
File version/Prouct version : 4.0.30319.235
Language: English (United States)
Date modified: 16-02-2012 22:50
I repro. You can get more insight into the bug with Debug + Exceptions, tick the Thrown checkbox for CLR exceptions. That will stop the program when an internal exception is thrown by the clipboard code in the framework. The IDataObject.GetDataHere() implementation method fails with a COM exception, "Invalid FORMATETC structure (Exception from HRESULT: 0x80040064 (DV_E_FORMATETC))".
There is something wrong with the format. That becomes clear when you set a breakpoint after the Clipboard.SetDataObject(obj) statement. And put Clipboard.GetDataObject().GetFormats() in a debugger watch expression. I see:
"System.Collections.Generic.List`1[[ClipboardTest.Program+Element, ConsoleApplication1, Version=1.0.0.0, Culture=neutral, Public"
Note how the string is truncated, the PublicKeyToken part got mangled. You can arbitrarily alter this truncated string by changing the namespace name and the project name. Make them short enough and the program won't fail.
Clearly this is the cause of the problem. The string length is clipped to 127 characters, any type whose full name is longer than that is going to cause this failure. With a high likelihood that this will be a generic type since they have very long names.
Please report this bug at connect.microsoft.com. Your code demonstrates the bug very well, just posting a link to it in your bug report will be sufficient. I don't have a very good workaround, ensuring the name is short enough is not very practical. But you can with code like this:
// Put it on the clipboard, use a wrapper type with a short name
var envelope = new List<object>();
envelope.AddRange(obj);
Clipboard.SetDataObject(envelope);
// Retrieve from clipboard, unwrap back to original type
envelope = (List<object>)Clipboard.GetDataObject().GetData(typeof(List<object>));
var retval = new List<Element>();
retval.AddRange(envelope.Cast<Element>());
return retval;
UPDATE: this bug is reported fixed in VS2013.
I have the following static property defined:
namespace Foo
{
public class Bar
{
private static byte[] aes256Key = null;
internal static byte[] Aes256Key
{
get
{
if (aes256Key != null)
{
return aes256Key;
}
aes256Key = new byte[32];
// Fill in key...
return aes256Key;
}
}
}
}
In another class within an internal namespace, I am accessing this property:
namespace Foo.Cryptography
{
public class SymmetricCryptography
{
internal static void EncryptFile(
string sourceFile,
string destinationFile)
{
// <snip>
AesManaged aes = new AesManaged();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.Key = Bar.Aes256Key; // Accessing the key here
// <snip>
}
}
}
Foo.Cryptography is used by an executable console application. When I run this console application manually from my build environment, I don't see any issues. However, when the executable is run within the context of the build process (on a server with a potentially different environment), I see the following runtime exception:
The type initializer for 'Foo.Bar' threw an exception.
The executable project in VS2008 has a reference to the Foo project which defines the Foo namespace.
Am I doing anything fundamentally wrong here? What could be causing this?
It's really hard to work on 'static world' without seeing the complete code. Nonetheless, following are few area that you can work on (personally) in order to find the cause.
aes256Key = new byte[32];
// Fill in key...
return aes256Key;
It's reasonable to check the possible exception in your 'Fill in key' logic
Define a static constructor for this Bar and initialize all your static fields.
Ensure you call following RuntimeHelpers.RunClassConstructor(typeof(Bar).TypeHandle)
before even accessing any static/instance field/member/method.
static void Main(string[] args)
{
RuntimeHelpers.RunClassConstructor(typeof(Bar).TypeHandle);
byte[] bt = Bar.Aes256Key;
}
RuntimeHelpers.RunClassConstructor does ask the runtime to call the static constructor regardless of the reasons specified in the CLI. This ensure deterministic unit initialization order. This is necessary because type initializer believe in Lazy initialization.
Foo.Aes256Key won't even compile, because Foo is your namespace...
Are Foo.Cryptography and Foo.Bar in the same dll? Sounds like a dependency problem like it just can't find the dll on the hard drive that contains Foo.Bar.
Edit: Okay the above is obviously not the problem...
Probably a class you're using in the initializer requires a dependency that's not on the production machine... I don't see anything in your code but maybe it's in the part you left out. I would assume you have the full .net framework loaded on the production machine. Are you using any objects in the part of the code you left out that would directly or indirectly call code from any other in house or 3rd party dlls?
Another Edit: Actually I don't think code in the part you left out would be able to cause this error because it shouldn't run automatically when the class initializes. Are you sure there's not any other code you're leaving out? I don't see anything here that looks like it could cause that kind of exception.
It looks like "private static byte[] aes256Key = null;" is the only line even capable of causing this exception, but I think it's pretty clear that this line is not going to do that.