Script# Wrap WebGL? - c#

How would one go about wrapping WebGL in Script#.
I tried to add stuff to the source code but get compile errors I don't understand.
[ScriptIgnoreNamespace]
[ScriptImport]
[ScriptName("webGL")]
public sealed class WebGL
{
[ScriptName("fooGL")]
public void Foo(string test)
{
}
}
Error 1 The base class or interface 'System.FormatException' in
assembly 'mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089' referenced by type
'System.UriFormatException' could not be
resolved c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll Web
Or is there a way better way to add WebGL support as a lib rather then adding it directly to the main source?
EDIT: Looks like that compiler error was coming from VS from auto adding System.dll to the project and it shouldn't be. After removing it now compiles. So now the question is what is the best way to wrap a javaScript API in Script# ??

You should look at the S# source on github for how wrappers are written. They're simply classes tagged with ScriptImport attribute and the internal methods/properties have empty values/bodies.
Look at the source here.

Related

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.

Protbuf-net Compiling to DLL string[] causing corrupt dll

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!)

Recompiling the OpenXmlSdkTool.Core DLL with a anon-method and delegate error

I'm doing research into the OpenXmlSdkTools v2.5 and had a sneak peak inside the OpenXmlSdkTools.Core.DLL and saved it as a c# Project with ILSpy.
While this question is active, here is the OpenXmlSdkTools.Core.DLL as a way to quickly reproduce the problem I'm encountering.
When I tried to compile the single class library project, I get two errors about a missng reference to assembly 'System.Xaml'. eg:
The type 'System.Windows.Markup.IQueryAmbient' is defined in an
assembly that is not referenced. You must add a reference to assembly
'System.Xaml
The type 'System.Windows.Markup.IUriContext' is defined in an assembly
that is not referenced. You must add a reference to assembly
'System.Xaml
So I added the ref.
After that I'm stuck on what I hope is the last compile error and I can't figure it out.
Cannot convert anonymous method to type 'System.Delegate' because it
is not a delegate
type C:\TFS\ABC\src\OpenXmlSdkTool.Core\DocumentFormat.OpenXml.Tools\ApplicationExtensions.cs
10
Here is the code:
using System;
using System.Windows;
using System.Windows.Threading;
namespace DocumentFormat.OpenXml.Tools
{
public static class ApplicationExtensions
{
public static void DoEvents(this Application application)
{
application.Dispatcher.Invoke(DispatcherPriority.Background, delegate
{
});
}
}
}
I'm stuck and puzzled that its a decompiled DLL that should be easy to re-compile again. Do you think by me adding the Xaml reference its caused this problem? And why would I need to add the Xaml reference if the Core.DLL is a class library project and ILSpy didn't included it in the csproj file?
I've looked at all the other questions on here with the same error but none of them really helped.
Update
When you add System.Xaml.dll as reference to your project. The interface is declared there. Here is the doc.
So now I'm in a Catch22, if I add the Xaml dll it will solve the first 2 errors but then it will cause this other error.
After reproducing the issue on my machine, I found this http://staceyw1.wordpress.com/2007/12/22/they-are-anonymous-methods-not-anonymous-delegates/ (referenced from Convert this delegate to an anonymous method or lambda).
Adding a cast to Action solved the issue
application.Dispatcher.Invoke(DispatcherPriority.Background, (Action)delegate
{
});
But there are probably other solutions.

Unity application block 2.0 - The given assembly name or codebase was invalid

Interfaces (In the assembly named "Interfaces". In project :- Interfaces)
namespace Interfaces
{
public interface IDoSomeWork1
{
string DoSomeWork1();
}
}
namespace Interfaces
{
public interface IDoSomeWork2
{
string DoSomeWork2();
}
}
Dependencies (In the assembly named "Entities". In project :- Entities)
namespace Entities
{
public class ClassB : IDoSomeWork1
{
public string DoSomeWork1()
{
return this.ToString();
}
}
}
namespace Entities
{
public class ClassC : IDoSomeWork2
{
public string DoSomeWork2()
{
return this.ToString();
}
}
}
Class (In project :- UsingUnity)
public class ClassA
{
[Dependency]
public IDoSomeWork1 DoSomeWork1 { get; set; }
[Dependency]
public IDoSomeWork2 DoSomeWork2 { get; set; }
public void SomeMethodInClassA()
{
Console.WriteLine(DoSomeWork1.DoSomeWork1());
Console.WriteLine(DoSomeWork2.DoSomeWork2());
}
}
App.Config (In a console application project :- ConsoleUsingUnity)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<containers>
<container>
<types>
<type type="Interfaces.IDoSomeWork1, Interfaces"
mapTo="Entities.ClassB, Entities" />
<type type="Interfaces.IDoSomeWork2, Interfaces"
mapTo="Entities.ClassC, Entities" />
</types>
</container>
</containers>
</unity>
</configuration>
The client (In a console application project :- ConsoleUsingUnity)
public class Class1
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
// Load from config file
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(container);
ClassA classA = container.Resolve<ClassA>();
classA.SomeMethodInClassA();
}
}
And when I run the client, I get the following error at section.Configure(container);:-
The given assembly name or codebase
was invalid. (Exception from HRESULT:
0x80131047)
I am not sure If there is anything wrong with the config or the type. Could anyone please point out the mistake here?
In case anyone else ever has the same problem - I was also getting this error but had a slightly different problem. I was trying to load an assembly that clearly existed like the following:
Assembly.Load("C:\\Program Files\\MyProgram\\MyAssembly.dll");
After lots of trial and error I figured out that you aren't supposed to pass the path and you certainly aren't supposed to include .dll extension. The following fixed my issue:
Assembly.Load("MyAssembly");
Hopefully that helps someone else sooner or later!
Before I answer my question, I must state that the code posted above didn't give me any problem (build error etc.). It just gave me the error I stated in my question. The problem with Unity at this point of time is that It does not provide which assembly or a which types in the assembly could not be loaded. This is a requested feature.
In my case It was a missing assembly problem. I didn't reference Entities assembly in to the client application project. It seems that that "Entities" assembly could be resolved only at the run-time (since it didn't give me any compile time error). However, the run-time error was also not useful at all.
I had a look a Fusion Log viewer (It should be in the .NET SDK folder). What a gem of an utility It is. It can log all kind of assembly bindings (all or only failures) and It give a very neat description of which assembly could not load. Very helpful!
So, next time, you get this "The given assembly name or codebase was invalid" error, try Fusion Log Viewer. It wont help you in finding which types couldn't be loaded. However,at least you will be sure all your assemblies are getting loaded correctly.
If you connect up the domain AssemblyResolve event you can get the assembly that has failed to bind.
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
There is a better way now!
Unity has a new version (currently 2.1.505.2) which clearly reports the details and lets you get to the bottom of it immediately.
You can find binaries and source here: http://unity.codeplex.com/releases
I found that the least time consuming method of finding which Type exactly failed to bind is the following:
Go to Sources section of Unity page at codeplex http://unity.codeplex.com/SourceControl/list/changesets
Select a version and download the sources
Build DEBUG version of Unity and Unity.Configuration (if your project uses more of unity assemblies, build them as well)
Remove references to unity from your project and add references to assemblies from step 3
In Visual Studio go to Debug > Exceptions and make sure Common Language Runtime Exceptions has a checkbox in the Thrown column.
Now go crash that thing. Execution will stop in Unitys' TypeResolverImpl.SearchAssemblies method and typeNameOrAlias parameter will hold the answer!
works like this
Dim dllData = System.IO.File.ReadAllBytes(dllFullPath)
Dim asb As System.Reflection.Assembly
asb = System.Reflection.Assembly.Load(dllData)
Dim cls As Object = asb.CreateInstance("namespace.class")
Please make sure, that you have added assembly references of the missing assembly in the project where your web.config file exists.
I was missing this. I already have added those assembly references in the project which was using Unity to resolve the class, but missed to add it in the parent project where configuration file was located. This has resolved my problem.

Why is XmlSerializer.Deserialize throwing a System.IO.FileLoadException?

I'm having a problem with XML deserialization that is baffling me.
I'm building an application that supports local customization of various services that it uses. I've implemented an abstract ServiceLocator class whose methods return various objects. Each custom installation is responsible for implementing a subclass of this and providing implementations of those methods. The meat of this class looks like this:
public abstract class ServiceLocator
{
public static void Initialize(string customFeaturesPath)
{
Assembly a = Assembly.LoadFrom(customFeaturesPath);
Type t = a.GetExportedTypes()
.AsEnumerable()
.Where(x => x.IsSubclassOf(typeof (ServiceLocator)))
.First();
Default = (ServiceLocator)a.CreateInstance(t.FullName);
}
public static ServiceLocator Default { get; private set; }
public abstract DefaultValuesContainer CreateDefaultValuesContainer();
}
This works just fine: I get the path to the custom features assembly from the application configuration file, the program calls Initialize, and then the application can call the various methods on ServiceLocator.Default and they return the appropriate custom implementations of the services.
One of these services is a DefaultValuesContainer. This is a simple object that exposes properties whose values need to be persisted in a user settings file. The idea is that I can serialize this object into a single user setting of type string. It makes for a user setting file that you wouldn't want to edit manually, but I'm cool with that.
Here's a concrete implementation of ServiceLocator.CreateDefaultValuesContainer:
protected override DefaultValuesContainer CreateDefaultValuesContainer(string serializedXml)
{
DefaultValuesContainer c = new ClientDefaultValuesContainer();
if (string.IsNullOrEmpty(serializedXml))
{
return c;
}
XmlSerializer x = new XmlSerializer(c.GetType());
return (DefaultValuesContainer) x.Deserialize(new StringReader(serializedXml));
}
Now here's the thing.
I've built unit tests for this using NUnit. When I run the tests in the test fixture class that exercises the client custom features, they work. When I run the entire test suite, the last line of the above method throws this exception:
System.InvalidOperationException : There is an error in XML document (0, 0).
----> System.IO.FileLoadException : Could not load file or assembly 'ClientCustomFeatures, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Invalid pointer (Exception from HRESULT: 0x80004003 (E_POINTER))
----> System.ArgumentNullException : Value cannot be null.
Parameter name: path1
I'm kind of baffled as to why. The SetUp method still runs, and ServiceLocator.Default still returns an object of type ClientServiceLocator, which means that it has loaded the ClientCustomFeatures assembly. Indeed, the very method that's throwing the exception is in the assembly that I'm being told can't be loaded.
What is the XmlSerializer trying to do here? Why is it trying to load an assembly that's already loaded? What on earth does "Invalid pointer" mean? And above all, how should I be debugging something like this?
If your custom assembly does not know where to load the assembly containing the ClientCustomFeatures class, this will happen. This occurs when you've deployed your custom assembly to a location that is not in the path of your main assembly and your main assembly is not in the gac. So if your custom asseblies are loaded from sub directories of your main assembly this should go away. However, if they are located in arbitrary places, you'll have a problem because they need to load your main assembly as they need access to the ClientCustomFeatures type.
I've had problems with the assembly loader (Fusion?) when one assembly loads another assembly which itself has (non-GAC) references. YourDLL.XmlSerializers.dll might be one such assembly. Try turning off Visual Studio's option to automatically generate an XML serialization assembly (Project options) - this will remove the additional assembly (and hence the dependency on it).
Fusion Log Viewer
To help diagnose assembly loading problems like these, take a look at the Fusion Log Viewer (AKA fuslogvw.exe).
Fusion == the .NET component that locates and loads assemblies.
Try to replace the line:
XmlSerializer x = new XmlSerializer(c.GetType());
with:
XmlSerializer x = new XmlSerializer(c.GetType(), new Type[] { typeof(DefaultValuesContainer), typeof(ClientDefaultValuesContainer) });

Categories