• Visitors can check out the Forum FAQ by clicking this link. You have to register before you can post: click the REGISTER link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. View our Forum Privacy Policy.
  • Want to receive the latest contracting news and advice straight to your inbox? Sign up to the ContractorUK newsletter here. Every sign up will also be entered into a draw to WIN £100 Amazon vouchers!

You are not logged in or you do not have permission to access this page. This could be due to one of several reasons:

  • You are not logged in. If you are already registered, fill in the form below to log in, or follow the "Sign Up" link to register a new account.
  • You may not have sufficient privileges to access this page. Are you trying to edit someone else's post, access administrative features or some other privileged system?
  • If you are trying to post, the administrator may have disabled your account, or it may be awaiting activation.

Previously on ".NET 2.0 Detecting deserialization"

Collapse

  • TheRefactornator
    replied
    That makes more sense now - rock and hard place. When instantiating a descendant class, the base class methods / contructors need to be called directly by the descendant..since you're not in control of these that makes this even more difficult to solve.

    Oh the joys of OO. Good luck.

    Leave a comment:


  • ASB
    replied
    Yes, that fine. But sadly is not the situation I am in.

    The class does not implement ISerializable and I am trying to avoid having to do so because it a base class which is inherited all over the place. ISerializable would need to be implemented in all the derived classes - and I am not in control of these. [aiui the serializer won't call the base implementation of the method - but I need to check this further; I couldn't get it to work yesterday]

    The properties in question are a few properties in the base class.

    Leave a comment:


  • TheRefactornator
    replied
    Sorry I don't get it. Below is some sample code to show the method I'm thinking of and it demonstrates that the serialization constructor is called ONLY when the class is being instantiated by the deserialization process. Client classes attempting to instantiate this class directly cannot use the serialization constructor because it has the protected access modifier.

    So as mentioned earlier you can set your flag in the serialization constructor to enable the prop setters if you need to, but clients directly instantiating the class can never do this and this means if the flag is not set and a client attempts to call one of the prop setters you are able to throw your exception. Then if you also implement IDeserializationCallback.OnDeserialization you can switch the flag off at the end of the deserialization process if you need to.

    Perhaps you're attempting to avoid doing something like this..or it's just too ugly..but I can't see why it doesn't work.


    using System;
    using System.Runtime.Serialization;
    namespace ClassLibrary
    {
    [Serializable]
    publicclassSerializableClass: ISerializable
    {
    ///<summary>
    /// Initializes a new instance of the <see cref="SerializableClass"/> class.
    ///</summary>
    public SerializableClass ()
    {
    //Regular constructor for client classes
    }
    ///<summary>
    /// Initializes a new instance of the <see cref="SerializableClass"/> class.
    ///</summary>
    ///<param name="info">The info.</param>
    ///<param name="context">The context.</param>
    protected SerializableClass(
    SerializationInfo info,
    StreamingContext context)
    {
    //Serialization constructor
    //note this is a protected constructor therefore is only callable by the serialization process
    //and not by client classes attempting to instantiate this thing directly
    }

    #region ISerializable Members
    publicvoid GetObjectData(SerializationInfo info, StreamingContext context)
    {
    //do your custom stuff in here if you need to..
    }
    #endregion
    }
    publicclassClientClass
    {
    public ClientClass()
    {
    SerializableClass aclass = newSerializableClass();
    }
    }
    }

    Leave a comment:


  • ASB
    replied
    Originally posted by TheRefactornator View Post
    Can you reverse the logic? i.e. The prop setters are disabled by default and only enabled in the serialization constructor? It seems like this will work because if an empty class instance is created locally then all prop setters are auto-disabled for that instance, and they are only enabled when serialization is underway. It seems a simple solution but perhaps I'm missing something.
    Unfortunately not. Using default serialization requires a parameterless public constructor. Naturally I could add another private constructor, but the issue is I still cannot tell if the object is going to be deserialized or not.

    The calls are:-

    New, optional OnDeserialised, any other calls into the object. Whether or not the object is being deserialised (which is the only place the setting will be valid) is always indeterminate.

    Of course I could easily enough add logic into the other methods to detect the properties were set and the object was not deserialised (thus the sets are invalid) but this cannot happen until the client next does something with the object. Equally I could add a method for the client to call after construction to denote whether it was deserilized or not. But I want to be able to tell the client it's been naughty at the point it is.

    The workaround is to save the data locally in some local variables and populate the actual variables underlying the properties at the point OnDeserialized is called (as implied by yourself and DP). This gives a workaround but means I can't throw an IllegalOperation exception at the time a client populates said properties when it shouldn't.

    Hence I do really want to know "being deserialized", followed by "been deserialized".

    It does look as though the only viable choice in to add the OnDeserializing and OnDeserialized attributes to an apporpritate method to control it.

    Leave a comment:


  • DimPrawn
    replied
    Originally posted by TheRefactornator View Post
    That's exactly what I proposed.
    .
    Indeed, I was just trying to put it to him/her again.

    Leave a comment:


  • TheRefactornator
    replied
    Originally posted by DimPrawn View Post
    Surely you can set an internal bool once the serialization has been completed (IDesiralizationCallback) so that every public setter is then prevented from changing the data?

    So during deserialization the flag _readOnly is false and the properties are set and once deserialization is complete the flag is set the true and every property setter is guarded?
    That's exactly what I proposed.

    Originally posted by ASB View Post
    I thought that initially, but I don't think I can make it work.

    In the case where the object is deserialized the contructor will be invoked, thus I can set _readonly to false, the properties set and the deserialization callback made then I can set _readonly to true.

    However in the case where the object is created in my application the deserialization callback will not be made, thus I can't tell it is being actively deserialized. Granted I can get over this in a number of ways. It still leaves a situation where a client application can simply create an empty one and will have writable versions of the properites though.
    Can you reverse the logic? i.e. The prop setters are disabled by default and only enabled in the serialization constructor? It seems like this will work because if an empty class instance is created locally then all prop setters are auto-disabled for that instance, and they are only enabled when serialization is underway. It seems a simple solution but perhaps I'm missing something.

    Leave a comment:


  • ASB
    replied
    Originally posted by DimPrawn View Post
    Can you customise the serialization/deserialization code:

    http://www.hanselman.com/blog/HOWTOD...dAssembly.aspx

    Capture the code generated and then include it in your project. Modify to set the properties internally, set the actual properties to readonly. Use this code directly to serialize and deserialize.

    Any good?
    I think I'd probably use custome serialization in preference. It just "feels" as though I should have enough control to enable me to serilize and deserialize how I want to without having to do the faffing around. Obviously I accept "default serialization will do X". I just don't like the particular X they have chosen!

    Leave a comment:


  • DimPrawn
    replied
    Can you customise the serialization/deserialization code:

    http://www.hanselman.com/blog/HOWTOD...dAssembly.aspx

    Capture the code generated and then include it in your project. Modify to set the properties internally, set the actual properties to readonly. Use this code directly to serialize and deserialize.

    Any good?
    Last edited by DimPrawn; 11 June 2009, 10:12.

    Leave a comment:


  • ASB
    replied
    Originally posted by DimPrawn View Post
    Surely you can set an internal bool once the serialization has been completed (IDesiralizationCallback) so that every public setter is then prevented from changing the data?

    So during deserialization the flag _readOnly is false and the properties are set and once deserialization is complete the flag is set the true and every property setter is guarded?
    I thought that initially, but I don't think I can make it work.

    In the case where the object is deserialized the contructor will be invoked, thus I can set _readonly to false, the properties set and the deserialization callback made then I can set _readonly to true.

    However in the case where the object is created in my application the deserialization callback will not be made, thus I can't tell it is being actively deserialized. Granted I can get over this in a number of ways. It still leaves a situation where a client application can simply create an empty one and will have writable versions of the properites though.

    I suppose I could still do something with CallContext though.

    Overall it doesn't seem there is much of a solution, though I'll investigate Customer serialization with OnDeserializingAttribute/OnDerserializedAttribute. It lookas as though this might give me what I need.

    /

    Leave a comment:


  • DimPrawn
    replied
    Surely you can set an internal bool once the serialization has been completed (IDesiralizationCallback) so that every public setter is then prevented from changing the data?

    So during deserialization the flag _readOnly is false and the properties are set and once deserialization is complete the flag is set the true and every property setter is guarded?

    Leave a comment:


  • ASB
    replied
    Originally posted by TheRefactornator View Post
    Or perhaps implement the IDeserializationCallback interface on your bog standard Serializable class and prevent the class property set{} methods from setting the private member variables in IDeserializationCallback.OnDeserialization using a bool flag.
    Unfortunately that doesn't give me enough information. I need to to know it's actively being deserialized and IDesiralizationCallback only tells me it has been

    My requirement is to allow them to be set when deserializing but not otherwise (except locally).

    I could probably implement ISerializable but this seems a huge faff. [In an ideal world the 'set' would remain private. But this would mandate ISerializable. Write once properties are a right pain when it comes to serialization.

    Leave a comment:


  • ASB
    replied
    Originally posted by DimPrawn View Post
    Can you use the DataContractSerializer instead?

    http://msdn.microsoft.com/en-us/libr...erializer.aspx

    This can work with private fields which means you can make the public properties read-only using the DataMemberAttribute
    Unfortunately not. Can't go to .NET 3.5. Have to stick with .NET 2.

    Leave a comment:


  • TheRefactornator
    replied
    Or perhaps implement the IDeserializationCallback interface on your bog standard Serializable class and prevent the class property set{} methods from setting the private member variables in IDeserializationCallback.OnDeserialization using a bool flag.

    Leave a comment:


  • DimPrawn
    replied
    Can you use the DataContractSerializer instead?

    http://msdn.microsoft.com/en-us/libr...erializer.aspx

    This can work with private fields which means you can make the public properties read-only using the DataMemberAttribute

    Leave a comment:


  • ASB
    started a topic .NET 2.0 Detecting deserialization

    .NET 2.0 Detecting deserialization

    I have on object which a client wishes to serialize and deserialize - specifically via XML.

    The problem is this means I have to ensure that the properties are read write. But I don't really want to do this since the data is "set once". So, how can I detect that an object is currently being deserialized by the XML deserializer.

    Basically what I need to do isonly allow the property to be set during deserialization, IDeserializationCallback doesn't help since that only has OnDeserialization called after completion of deserialization.

    I think OnDeserializingAttribute/OnDerserializedAttribute might to appropriate so that I can detect deserialization is in progress. Anybody tried this ??

Working...
X