XmlSerializers with addin outlook - c#

I’m trying to create add-in for outlook and have issue with deserialization and antivirus program.
I’ve noticed that when my add-in tried to deserialize any data, .NET framework created temporary dll in “C:\Users\{UserName}\AppData\Local\Temp\" folder.
This dll existed very short time, but from time to time antivirus locked it and add-in thrown error message that file is used by another process.
I’m tried to get rid of temporary dll and found recommendations to use sgen tool for creation of XmlSerializers.dll.
I generated MyAssembly. XmlSerializers.dll with strong name and placed it to the folder with add-in (C:\Program Files (x86)\MyAddin). But it doesn’t help.
Then I tried to place MyAssembly. XmlSerializers.dll to GAC and then to outlook folder, but had no success. When dll was called from GAC I got following error message, but dll has no any reference.
"System.IO.FileNotFoundException: Could not load file or assembly or
one of its dependencies. The system cannot find the file specified."
Please add any thoughts how can I to get rid of temporary dll

When an XmlSerializer for a type is first constructed, internally the XML serialization engine generates c# code to serialize and deserialize the type, writes it to %TEMP% in temporary file(s), then compiles and loads the resulting assembly, finally deleting any temporary files. (Subsequent usages of XmlSerializer reuse the created assembly, see here for details.)
It looks as though your antivirus software is being ultra-aggressive at scanning any "unexpected" files created by the Outlook process, immediately trapping the creation of the file and scanning the results. While under most circumstances this would seem praiseworthy, it clearly conflicts with Microsoft's design for XmlSerializer.
So, what to do about this? You have several options:
Switch to DataContractSerializer, which does not use this architecture. DataContractSerializer is less flexible that XmlSerializer, however, and may not be able to parse your XML without preprocessing it.
Enable precompiled serialization assemblies. It's not sufficient to simply set GenerateSerializationAssemblies = On as is specified in the documentation, you have to jump through several hoops to make this actually work. See answers to Generating an Xml Serialization assembly as part of my build for ways to do it. I was able to make the accepted answer work with my old Visual Studio 2008 by editing my project file as described and then removing the Platform="$(Platform)" attribute. You might need to tweak the answer differently for your VS version.
After actually enabling pre-generated serialization DLLs I verified with Process Monitor that no files were written to %TEMP% when deserializing XML in a test console application.
See also here: Boost performance with Pre-generated XmlSerializers.
Update
After a bit of testing, I found that, if your root object does not exist in the assembly you are building, or if is a generic collection like List<T> or T [], then precompiled serializer assemblies are not used. However, making a non-generic subclass of List<T> re-enables serializer assemblies, e.g. public class RootObjectList : List<RootObject> { }.
For more, see here: All about XmlSerializer Performance and Sgen.
Convert your XML to JSON with Json.NET, then deserialize the JSON.
If your XML is simple, you could load it into an XDocument and query it with Linq to XML.

Related

Pre-generated XML serializer assembly

I have a Visual Studio program that connects to a web service and a VMware environment. Part of the process is to get connected and understand the XML that comes back (i.e. translate it in to custom objects) which involves compiling a proxy file (XML serializer assembly dll file).
I have tried to use this file in my Monotouch program, but for some reason, Monotouch doesn't seemingly want to know about the XML serializer assembly. It ignores it and so I receive XML nodes back, rather than the XML being mapped back to the correct custom object via the XML serializer assembly.
How can I get Monotouch to recognize the file and use it?
Neither Mono or any Mono-powered products (like MonoTouch or MonoDroid) support XmlSerializerAssembly.

Error loading assembly when retrieving from AppFabric cache

I ran into a weird issue today while debugging one of my projects. I use VS2010 / windows 7 home premium.
I have a project that uses Windows Server AppFabric Cache. I have configured everything, and have created two different C# projects (2 solutions) to test the AppFabric configuration. The project names are "AppFabricServer" and "AppFabricClient". This is just for testing and the naming convention doesn't mean anything specific. I use "AppFabricServer" to Add objects to AppFabric Cache and "AppFabricClient" project to retrieve.
Now, the problem is after running the "AppFabricServer" and then I try to run "AppFabricClient" after closing the "AppFabricServer", I get an error "System.IO.FileNotFoundException: Could not load file or assembly 'AppFabricServer". I don't understand in which way "AppFabricServer" project is related to "AppFabricClient" project.
The same thing happens vice-verse also - this means, after restarting the computer and if I run "AppFabricClient" project first (it also has a Cache writing module), I am not able to run "AppFabricServer" project (it has a Cache reading module as well). I get the same error -"System.IO.FileNotFoundException: Could not load file or assembly 'AppFabricClient".
The exception is thrown at the line where I try to retrieve data from the Cache - when I call the Get method of DataCache.
Can someone please help?
AppFabric utilizes the NetDataContractSerializer to serialize objects. This serializer encodes CLR type information. So, even if the shape of your objects is the same, it actually requires them to be the same types in the same assembly.
Therefore, take the object you are serializing out of the AppFabricServer assembly and put it in a third assembly that is referenced from both the AppFabricServer and AppFabricClient programs. That way, the CLR type information will be the same in both.

Assembly Serialization, Why?

I've read that assembly serialization (sgen.exe) can improve performance.
What exactly is providing the improvement?
Is it metadata on the Types? I would have thought this would be available through reflection! so why is it required in a separate assembly?
The serialization assemblies Data.XmlSerializers.dll which improve the performance of clients that use XML Web service proxies to communicate with servers is described under http://msdn.microsoft.com/en-us/library/bk3w6240.aspx.
If you don't do this the same work will be done at the first usage of XmlSerializer. In the blog Link is described additional setting in <system.diagnostics> area of the application.config file to see more what do XmlSerializer in the background.
In Visual Studio there are a spetion setting in the "Build" tab of project settings (see http://www.eggheadcafe.com/tutorials/aspnet/8eb0e68f-5496-4363-9cb9-dd68447ba187/xml-serializer-generator.aspx). So you not really need to use sgen.exe manually.
To more understand what sgen.exe do you can load an open source version of sgen.exe: xgenplus http://xgenplus.codeplex.com/.
I recommend you aslo to read SGEN XMLSerializer - should be .XMLSerializers.dll added as a reference to the current project or to the GAC?.
If you search in google for XmlSerializer and sgen you will find all the information and even more on the first page of the serch results.

SGEN XMLSerializer - should be .XMLSerializers.dll added as a reference to the current project or to the GAC?

I do some stuff with XMLSerializer class. Like a most of beginners I face with performance issue on app start. I read a lot of blogs, articles and finally use SGEN tool. Now performance looks to be ok but few things are still not clear for me.
1) Should I use SGEN syntax like this:
SGen.exe /assembly:MyAssembly /type:MyRootXmlType
or it's enough to just (I use this syntax currently, I have only one Serializable class in my assembly):
SGen.exe /assembly:MyAssembly
When /type parameter can be useful in practice?
2) I read on MSDN ( http://msdn.microsoft.com/en-us/library/ee704594.aspx )
This command generates the serializer
assembly
MyAssembly.XmlSerializers.dll, which
should be added as a reference to the
current project or to the GAC.
but on all other blogs and articles (for example on SO) I read that is enough to just put MyAssembly.XmlSerializers.dll into folder where MyAssembly exists.
So what is right?
3) It's enough to just generate .XmlSerilizers.dll and deploy it together with MyAssembly or should I add something to my code yet?
I don't think so but I would like to be sure that I will not have to change my code and "magic" happens automatically.
If you don't use the /type argument for sgen.exe then it will generate de/serialization code for all public types in the assembly. Note that the [Serializable] attribute is not used in XML serialization. I doubt you'd want this, use /type to keep the generated assembly small.
Adding a reference is not necessary, Xml serialization always tries an Assembly.Load() on the .XmlSerializers.dll assembly anyway. Plus, you'll never reference the generated XmlSerializationWriterXxx and XmlSerializationReaderXxx classes directly in your code. It does have one advantage, the build system will automatically copy the assembly when you include the project in a solution.
Installing it in the GAC is only worth considering when different apps serialize and deserialize the XML file. You can provide other apps with the .XmlSerializers.dll assembly by copying the assembly by hand as well. Which is a bit error prone, use your own judgment here. Check the previous paragraph for a way to automate the copy.

Requiring library consumers reference additional assembly when using certain types

I have library code that uses ICSharpCode.SharpZipLib under the hood to make it easy to use ZIP files as data sources when running integration tests.
As it stands, if I reference my library from another project, the other project will compile just fine, but when it accesses the code that uses SharpZipLib, I get an exception for it not finding the zip library:
failed: System.IO.FileNotFoundException : Could not load file or assembly 'ICSharpCode.SharpZipLib, Version=0.85.5.452, Culture=neutral, PublicKeyToken=1b03e6acf1164f73' or one of its dependencies. The system cannot find the file specified.
If the types in my library derived from a class in SharpZipLib, it'd generate a compile error CS0012. What other ways are there for triggering a CS0012, so that using code that requires SharpZipLib (but doesn't clearly indicate it) would cause consumer code to fail compilation?
I've had similar problems in the past when I've used libraries like DeftTech.DuckTyping under the hood. I'd add my library code to a new project, start working, compile, run, and then suddenly hit an edge case that I'd used duck typing to get around and get a runtime error.
What I'd most like is to have the same behavior as if I'd derived from a type in the 3rd-party library, so that a reference to my derived type generates a CS0012:
The type 'type' is defined in an assembly that is not referenced. You must add a reference to assembly 'assembly'.
You only get compiler errors if you are DIRECTLY interacting with libraries that aren't referenced.
If you use other libraries that internally use a third party library then you will never get a compiler error. The reason is this just doesn't make much sense having a compile error because:
It does not affect compiling at all, so why a compiler error?
Your application MIGHT run correctly, because there is no guarantee the third-party library EVER gets called.
It might actually break several libraries, that e.g. do reference external libraries for debugging, but just don't ship them for release.
Edit: If your problem is that you are forgetting about the third-party library you can simply reference it directly from your application even if you never use it. Then e.g. Visual Studio will automatically copy it to your output bin folder and includes it in setups, and so on.
If you're seeing this while in Visual Studio it's probably because the ICSharpCode.SharpZipLib.dll isn't being copied to the build folder of your "other" project.
So this won't be a problem when you distribute your library for consumption by third parties because the ICSharpCode.SharpZibLib.dll will be in the same folder as your library.
During development and testing though it can be a bit of a hassle. Generally when setting up a multi-project solution I just have all the projects target their Output folder to a single solution-wide Build folder. That way all the dependencies are copied to the same location for testing.
You just have to copy ICSharpCodeSharpZipLib.dll to C:\Windows\assembly and your problem will be solved.

Categories