| Perfil de PaulioIT BytesBlogListasScraps | Ajuda |
|
|
22 de maio nHibernate CreateQuery gotchaAs an nHibernate newbie I wasted a bit of time trying to get the Hibernate Query Language (HQL) CreateQuery function to work for me. Even the simplist query failed to work, e.g. I have a class MyEntity and I wrote something like;
session.CreateQuery("From MyEntity as myEntity")
then nHibernate would give me errors such as "in expected", or "uknown token as". I'd read a bit about problems where the mapping may not have been processed yet but that couldn't be the case because I'd previously successfully loaded a MyEntity. However, it did prompt me to ask the SessionFactory for the metadata about MyEntity. What I spotted was the EntityName included, now obviously, the fully qualified name of; MyNamespace.Bla.Yada.MyEntity. Therefore the correct syntax is;
session.CreateQuery("From MyNamespace.Bla.Yada.MyEntity as myEntity")
I've yet to find a way to add namespaces to the query but at least the thing works now!
26 de março Great talk about ADO Data ServicesJust finished watching a really could talk from Mix09 about ADO.NET Data Services. I've been wondering about where the business rules really fit with ADO.NET DataServices and the Entity Framework. This has gone a long way to helping me understand it, I really recommend it.
31 de março The wacky world of serializers Recently I'd set my debug exception handling to catch pretty much every exception thrown and I kept seeing a rather strange error...
System.IO.FileNotFoundException occurred
Message="Could not load file or assembly myType.XmlSerializers" What was odd about this error is that although the type in question was being serialized it wasn't overloading any serialization code, so why the exception? The question did the rounds of the development team and a colleague discovered the truth. It turns out that as an optimization .net searches for a special optimized serialization version of the type, based on the type's names. If it finds it, it uses it. If not a file not found exception is raised and then automatically handled and the default serializer is called into play. What I find odd about this concept is that in order to use an optimization, that I would have to write anyway, the framework makes an expensive disk access followed by an exception. So the effect is that if I don't implement the optimization I get an extra performance hit!
04 de setembro Simple way to Serialize an object to a stringI'm the first to admit that the number of streams and serializing methods can be confusing. I wanted a quick and simple way to test my serialize code by persisting an object into a string. A quick google later and I had found a number of overly complicated examples, so here is my very simple method... XmlSerializer serializer = new XmlSerializer(typeof(MyType)); string resultingXml = null; using (StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture)) { serializer.Serialize(stringWriter, myObject); resultingXml = stringWriter.ToString(); } 21 de agosto Setup.EXE bootstrap for WiX and/or msiCreating msi files using WiX is normally great, however one thing that is terrible is when you want your users to upgrade a product. Rather than simply selecting the msi they are required to issue
MSIEXEC /i My.msi REINSTALL=ALL REINSTALLMODE=vomus Not exactly user friendly. So it was time to create a nice setup.exe bootstrap to detect when an upgrade was needed and issue the horror statement. A quick tour around the Windows SDK brought up the their sample. Written in Win32/C++ it seemed to be over complicated especially since I know the product is only ever going onto machines with .net pre-installed. So I wrote the following little csharp console code that does the trick for my requirements. static void Main(string[] args){ Type componentType = Type.GetTypeFromProgID("WindowsInstaller.Installer"); if (componentType == null){ Console.WriteLine("Windows Installer is either not installed or could not be located"); return;} object componentInstance; try{ componentInstance = Activator.CreateInstance(componentType);} catch (Exception e){ Console.WriteLine("Windows Installer is either not installed or could not be located: " + e.Message ); return;} object returnType = componentType.InvokeMember("Products", BindingFlags.GetProperty, null, componentInstance, null); IEnumerable stringList = (IEnumerable)returnType; bool foundProduct = false; foreach (string product in stringList) { if (product == "{YOURPRODUCT_GUID}"){ foundProduct = true; break;} } if (foundProduct){ System.Diagnostics. Process.Start(@"msiexec", @"/i My.msi REINSTALL=ALL REINSTALLMODE=vomus");} else{ System.Diagnostics. Process.Start(@"msiexec", "My.msi");} } 18 de agosto Fun with EnumsOne of the seemingly lesser known features of Enums is their ability to convert to and from the name rather than the value, so I thought I'd do a quick refresher. Consider the following Enum... Medal.Bronze = 0 Medal.Silver = 1 Medal.Gold = 2 The majority of cases people leave it as an int (can be any non-char integral type). However, what happens when you want to store/persist the type? If I was to save this to a disk file I might choose to use XML and have a result like... <Medal>2</Medal> Then when I load the XML back I can easily convert it back... Medal medal = (int)Convert.ToInt32("2"); However, I don't actually like this, the value of 2 has no real meaning to the reader, I'd much prefer to see <Medal>Gold</Medal> Well it is possible. To save the name rather than the value you can use ToString and a format string... medal.ToString("G"); Reading the name back into the enum uses the often overlooked Parse method... Medal medal = (Medal)Enum.Parse(typeof(Medal), "Gold"); Admittedly this doesn't solve localization problems of having XML, "human readable" but I prefer it. 08 de julho NotSupportedExceptionI had written some code that implemented a particular interface where I only wanted to support a small set of the functions. So when I used Visual Studio's snippet I left the throw new Exception("Not yet implemented") alone. My ever knowing colleague explained to me that this was a known problem with the snippet and it should really use... throw new NotSupportedException I thought this was a great find since I hated raising such a woolly exception. 01 de julho Support implicit/explicit conversion in C# for VB.NETToday I hit an annoying problem with VB.NET using components written in C#. The basic problem is that I have an object called Field with a Value property of type object written in C#. The client code is written in VB.NET and wants to access the Field's value without specifying the Value property, e.g. Dim myField as Field = new Field() myField.Value = 13 ... If CInt(myField) = 13 or myField = 13... The initial problem is that a Field is not an int, so you'll get an invalid cast, fair enough. So I implemented the implicit/explicit conversion operators available in C#. Field myField = new Field(); myField.Value = 13 ... if ((int)myField==13)... The above, written in C#, now works but the previous VB.NET still fails! The problem is that VB.NET simply doesn't call op_Implicit/op_Explicit functions exposed by the C# code. Delving into the Visual Basic engine you can see that under the covers it use IConvertable to do all of its conversions. So if you want VB.NET to understand that House = 7 really means House.Number = 7 then you need to implement IConvertable in the C# component. After implementing IConvertable the above code sprang into life. 02 de junho Mono == FrustrationFinally managed to find a 1/2 decent code editor for the Mac (smultron) so I thought I port my Wake Up On Lan code to mono and run it on the Mac. What an annoying tool mono is. After using the tools of dinosaurs (Terminal) I asked the compiler to do its work. It came back with... (4, 255+) Expecting ';'. Well fine but what the **!* does that mean? I sort of assumed that it was column and row. So I went to the 5th line and stuck in some rubbish characters to confirm my theory... (1, 124) Expecting ';'. Eh? Now I understand why they don't supply some lovely rich IDE but I would hope that the compiler gives useful error messages not some random value that makes it impossible to use. Ok I'll look up the error codes, couldn't find any documentation on that. Off to the forums, surely I must just have something configured incorrectly. What forum, must be a community support. Nope some link to a commercial company. Ah here we go...an email list. What is this? A tool for the uber geek who takes pleasure in finding the most painful and awful way to communicate? I've half a mind to simply give up on this if "they" simply want to keep it a dark room project. [Edit] A plus in Mono's column... Although the error message is still *rubbish* I finally discovered that I had some generics code and I was using the v1 compiler. So I downloaded the latest version of Mono and updated (nice that it updated the existing version) and used the gmcs compiler (v2) and the file compiled without problems, so expect a WOL for OSX in the near future. 24 de abril Programmatically Wake Up On Lan using .netI've been meaning to write a web site to list a number of machines and allow the user to issue a Wake Up On Lan command to them. Looking around the web I found a great VB sample to issue the command. However, I didn't want to pollute my nice c# with yukky VB
using System;using System.Collections.Generic;using System.Text;using System.Net;using System.Net.Sockets;using System.Globalization;
namespace Utilities.Network{ /// <summary> /// Utility class to wake machines up that are configured to "Wake Up On Lan" /// </summary> /// <remarks>Code orginally written in VB from http://www.lucamauri.com/snippet/snip.aspx?id=6</remarks> public sealed class WakeUpOnLan{ /// <summary> /// Initialise using the default values /// </summary> /// <remarks>The default IPEndPoint transmit on port 7. Other choices for WOL are port 0 or 9</remarks> public WakeUpOnLan(){ this.endPoint = new IPEndPoint(IPAddress.Broadcast, 7);} /// <summary> /// Initialise using a specific port /// </summary> /// <param name="port">A valid port number</param> /// <remarks>If the port number is invalid, the IPEndPoint is created to port 7. Ports normally used for WOL are 0, 7 or 9.</remarks> public WakeUpOnLan(int port){ if (port >= 0 && port < 65535){ endPoint = new IPEndPoint(IPAddress.Broadcast, port);} else{ endPoint = new IPEndPoint(IPAddress.Broadcast, 7);} } /// <summary> /// The IPEndPoint object that will act as a trasport for the packet. /// It is automatically created by New statement, but you can modify it or read it. /// </summary> /// <value>An IPEndPoint object</value> /// <returns>An IPEndPoint object</returns> /// <remarks>Normally there is no need to change this manually.</remarks> public IPEndPoint EndPoint { get{ return this.endPoint;} set{ this.endPoint = value;} } /// <summary> /// The target machine Network Interface Card MAC address. /// It must be dash-separated, i.e. in the 11-22-33-44-55-66 form /// </summary> /// <value>A string with dash-separated values</value> /// <returns>A string with dash-separated values</returns> /// <remarks>The standard (IEEE 802) separator for cotet are dash (-) and semicolon (:). I resolved to use dashes only in order to avoid any possible confusion and misunderstanding with upcoming IPv6 addressing space.</remarks> public string MacAddress{ get{ StringBuilder textMAC = new StringBuilder(); foreach (byte currByte in this.macAddress){ textMAC.Append( "-");textMAC.Append(currByte.ToString( "X2"));} return textMAC.ToString().Substring(1);} set{ if (String.IsNullOrEmpty(value)){ throw new FormatException(MacFormatMessage);} Queue<byte> values = new Queue<byte>(); string[] hexValues = value.Split('-'); if (hexValues.Length != 6){ throw new FormatException(MacFormatMessage);} foreach (string currByte in hexValues){ byte convertedByte; if (Byte.TryParse(currByte, System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture, out convertedByte)){ values.Enqueue(convertedByte); } else{ throw new FormatException(MacFormatMessage);} } this.macAddress = values.ToArray();} } /// <summary> /// Total bytes sent by WakeIt method. It is 0 until the method is called at least once for this class instance. /// </summary> /// <returns>Integer value, total bytes trasmitted</returns> /// <remarks></remarks> public int BytesSent{ get{ return this.bytesSent;} } /// <summary> /// It represent the Magic Packet broadcasted. /// </summary> /// <returns>String containing the text parsing of the Magic Packet</returns> /// <remarks></remarks> public string PacketSent{ get{ return packetSent;} } /// <summary> /// Creates a WOL Magic Packet, the datagram that will awake the target PC upon broadcast on the network. /// </summary> /// <param name="macAddress">An array of byte representing the target machine Network Interface Card MAC address</param> /// <returns>An array of byte representing the Magic Packet</returns> /// <remarks>This method can be used indipendently from the rest of the class. If necessary it can create a Magic Packet just providing the MAC address.</remarks> private byte[] MagicPacket(byte[] macAddress){ if (macAddress.Length == 0){ throw new FormatException("Invalid MAC address");} byte[] payloadData = new byte[0]; StringBuilder packet = new StringBuilder();
payloadData = new byte[HeaderLength + MacLength * repMAC]; for (int i = 0; i < HeaderLength; i++){ payloadData[i] = Byte.Parse("FF", System.Globalization.NumberStyles.HexNumber);} for (int i = 0; i < repMAC; i++){ for (int j = 0; j < MacLength; j++){ payloadData[HeaderLength + i * MacLength + j] = macAddress[j]; } } foreach (byte currLoad in payloadData){ packet.Append( "-");packet.Append(currLoad.ToString( "X2"));} packetSent = packet.ToString().Substring(1); return payloadData; } private int SendUdp(byte[] payload, IPEndPoint endPoint){ int byteSend; if ((payload != null) && (endPoint != null)){ Socket socketClient = new Socket(endPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);socketClient.Connect(endPoint); byteSend = socketClient.Send(payload, 0, payload.Length, SocketFlags.None);socketClient.Close(); } else{ byteSend = 0; } return byteSend;} /// <summary> /// It is the main method of the class. It must be called after the MAC address has been set. It does not return any code, you can see the result of the operation with the bytesSent and packetSent properties of this class. /// </summary> /// <remarks></remarks> public void WakeIt(){ bytesSent = SendUdp(MagicPacket(macAddress), endPoint); } const int HeaderLength = 6; const int MacLength = 6; const int repMAC = 16; const string MacFormatMessage = "Mac Format should be; XX-XX-XX-XX-XX, e.g. 00-13-71-BC-C2-CE"; IPEndPoint endPoint; byte[] macAddress; int bytesSent = 0; string packetSent; } } Calling the instance of a ContextBoundObjectContextBoundObjects are useful for implementing Aspect Orientated Programming (AOP), however one thing that I wanted to do was to call methods on the instance that the context "shadows". Since it caused me some pain I though I'd publish it here to avoid others suffering as I did.
1. Save the MarshalByRefObject that is passed into the AttributeContext, this represents the object that we're shadowing
public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)2. Assuming you can put your AOP attribute on any class, you'll need to get hold of the type that is really inside the Marshalled object. There are a number of ways of doing this, this was the first mechanism I tried and it worked so I left it at this
private void Postprocess(IMessage msg, IMessage msgReturn)...
...msg.Properties[ 3. Marshal the object into the discovered type and call methods on it. All done.
Type sourceType = Type.GetType(typeName); ObjRef objectRef = RemotingServices.Marshal(this.sourceMarshalByRefObject,null,sourceType); object o = Activator.GetObject(sourceType, objectRef.URI); if (o is IMyKnownInterface){ IMyKnownInterface myInterface = (IMyKnownInterface)o;myInterface.MyMethod() ... 19 de março Windows Presentation Framework, first lookI had my first real play with the Windows Presentation Framework (WPF). The first thing that struck me is how like the web model it is. For example, through the use of various services it provides the cascading down of properties and the bubbling up of events. So you can mark a grand-parent property, e.g. color, and if any child node doesn't specify a colour they'll automatically have their parents colour value. Similarly the event model is like the web. You fire an event in a child element and the event can bubble up through all of its ancestors, any of which can handle the event. I only managed a very quick play with the beta Visual Studio Add-in, created a quick "hello world" style application from a button click. I'm not sure if it's a clumsy beta or it going to work this way but I didn't get my nice event handler template by double clicking the button. Oh no, I had to guess at event handling code (almost identical to the usual one) and guess where in the Xaml I had to add the click attribute to wire-up the event. But it worked and I hope to have a longer play soon. How to ignore a field/property during serializationI've hit the problem of serializing a property for the last time. When you create a type that contains a non-serializable type, in my case a CultureInfo class, you cannot automatically serialize the type - you get issues about "does not contain a public constructor", "problem reflecting the type", etc. Unfortunately this isn't caught at compile time and you have to wait until an attempt is made to serialize the containing object. What to do about it? The more complicated choice is to write some custom serialization code, but really, most of the time I just want to serialize pretty simple objects. So my preference is to mark the class as serializable and let the client choose how to serialize it, i.e. via Binary or Xml "serializers". The framework provides a couple of attributes for this, and this is where the gotcha lives. The first attribute, [NonSerialized], should be applied to field members and informs the standard serialization methods to ignore the field. The second attribute, [System.Xml.Serialization.XmlIgnore], should be applied to public properties and informs the Xml Serializer to ignore the property. The combination of the two should be enough to stop the field from being serialized regardless of the serializer the client chooses to use. Quick pseudo example: [NonSerialized], private SomeUnFriendlyType myType: [System.Xml.Serialization.XmlIgnore] public SomeUnFriendlyType MyType() .... 10 de fevereiro Using Settings in C# Windows Forms applicationsIt suprised me how poor the documentation is for using Settings with a Windows Form application written in C#. I noticed recently the following article posted on the MSDN site, http://msdn2.microsoft.com/en-us/library/aa730869(VS.80).aspx. However, there is an easier way. Create the settings you want to persist in the projects settings page as normal. Then, rather than hand coding the mapping between the setting file and your UI controls go to the form designer. In the properties of the UI control select Application Settings->Property Bindings. Map the appropriate property (e.g. Text) to the required setting value. All done, well not quite. If you want to persist the changes you need to add the following to the forms closed event...
Properties.Settings.Default.Save(); There all done, persisted settings with only one line of code....nice. 24 de janeiro Generic dictionary indexer behaves differentlyToday I discovered, the hard way, that if you ask for a key value that doesn't exist in a generic dictionary you get an exception, whereas for specialised dictionaries (or your own derived ones) you get null. This was especially annoying has I have a load of code expecting null and a colleague changed the dictionary to a generic one. So I had to change the indexer to do a quick "contains key" to return null if the key doesn't exist. 22 de janeiro Who changed that file?Writing a file watcher program at the moment but I've hit a problem, I can't seem to discover who changed the file last. I'm sure Windows keeps the information but I can't find it. Ok, so the users can turn on file auditing so I guess it's no big deal but I can't help thinking I'm just missing something. The other bit of information I was trying to locate is the 'File Version' of a DLL. After following seemingly countless dead ends looking at FileInfo, FileAttributes, etc I discovered that that this information is...under System.Diagnostics! Obvious really!? 08 de dezembro ASP.NET why doesn't error?Ok it is a strange title but... One of my the most problematic areas of ASP.NET is the combination of Viewstate and the Page Life-Cycle. If you attempt to access the Viewstate before it's ready then not only do you get incorrect results for that call but you corrupt the state for subsequent calls too. So given that ASP knows where it is in the life cycle and that you're trying to access the state, why doesn't simply raise an exception? If nothing else it would save about 100Gb worth of forum posts! In a similar vein I was working on a HtmlInputText control the other day and fell for another issue. As a good ASP developer I knew that the ID I've given the control will be changed to some odd unique name with lots of "ctl_" text stuck in-front of it. (If I say I want to uniquely name it and take that responsibility then it should only use my ID, grrrr). So I when I wanted to generate some Javascript to access the control I passed in myControl.ClientID. However, my Javascript failed saying the object was null. Odd. A quick review of the code I noticed that I was accessing the ClientID before I'd added the control to the page. Ok, that makes sense, but again why is the ClientID populated with the name of the ID only before it's been added to the page? Surely if you access the ClientID before the *page* has correctly populated it, then it should error? Oh well, just yet another pitfall to side-step. 12 de novembro My first Mono applicationFinally managed to write my first program on Mac OS-X thanks the Mono project. Unfortunately there isn't a simple (free) IDE for it yet (at least not without installing lots of odd Unix X-like components). But anyway it was nice to see "hello world" appear in a Unix window all written in C#, I'm easily pleased! 09 de agosto URI or Windows file format?I've been writing a component that streams a file to the user based up a supplied path. The path can either be a Uniform Resource Idendfier (URI) or a standard Windows path, e.g. C:\My Documents\MyDoc.doc
The problem is that the majority of the streaming enabled .net components accept either a URI or a file path but not both. Therefore my code has to understand if the passed in string contains a URI or a file path. My first port of call was Uri.IsWellFormedUriString which returns true if the string contains a URI. So if it's a valid URI then I use the URI Streaming components otherwise I'll use the FileStream components...however, what if they've supplied a URI but have simply messed up the encoded, this would fail and then attempt to supply a dodgy URI to the file streaming code. I thought I was going to have do some exception catching (yuk) but to my suprise File.Exists doesn't seem to care about the format of the file path, either it can see it or it can't, regardless of what rubbish you enter. So I can happily assume a file path for any invalid URI and providing I check that the file exists I don't have to do any nasty exception handling
I also encountered some slightly quirky behaviour to URI.TryCreate that creates a URI or fails without raising an exception. I started to use this but discovered that it always seemed to successfully create a URI (using the file:// schema) no matter what invalid text I threw at it. So be careful when using that method.
05 de agosto Serializable DictionaryWhilst writing a WinForm with a TreeView I came across ye olde problem of using components that don't support Serialization. In my case I was shadowing the TreeNodes with my own Dictionary object, actually a generic myDictionary<string, myObject> only to discover that Dictionary doesn't support Serialization either
So faced with writing some custom serialization code I quickly reached for Google and found...
So now I had a serializable dictionary I just had to sort out my components. The first annoying problem was that my component contains a field of type TreeNode. So like a good .net developer I added the NonSerialable attribute to the field. But when I went to serialize the component it complained it couldn't find out what a TreeNode was, grrr. So the mere fact of exposing a public property of TreeNode, even though the resulting serialization won't use it, is enough to fail the XmlSerializer. I've not thought too much about a solution to this since I only use this class internally so I changed the property from Public to Internal and that did the trick...although what if I did need to expose that as a public method? So the code now happily writes my dictionary of objects to disk. |
|
|