Hi again!
Here's the code. It's a few classes, so I hope you manage to see what's
what.. :)
There's a business object base that's used in the business object collection
base class, and derived business objects in according collections.
These objects are to be used with the component designer in Visual Studio
for ASP.NET pages with DataGrids etc. To get the serializers to ignore Site
and Containers, we've made a custom MarshalByValueC omponent class.
I tried to make the base classes implement the necessary functionality for
Xml Serialization, so I'll only post those. Instantiating an XmlSerializer
for the collection base still fails.
MarshalByValueX S:
-------------------------
using System;
using System.Componen tModel;
using System.Xml.Seri alization;
namespace Project.Model.T ypes
{
/// <summary>
/// Implements IComponent and provides the base implementation for
remotable components that are marshaled by value (a copy of the serialized
object is passed).
/// </summary>
/// <remarks>
/// <para>A component can be contained in a container. For each
component in a container, the container creates a site that it uses to
manage the component. The component interacts with its container primarily
through a container-provided ISite, which is a repository of
container-specific, per-component information.</para>
/// <para>Notes to Inheritors: When you inherit from this class, you
can override the Dispose, Site, and the GetService methods.</para>
/// <para>Notes to all: This class is identical to
System.MarshalB yValueComponent , except that this one has XmlIgnore and
SoapIgnore on Site and Container..</para>
/// </remarks>
[Serializable]
public class MarshalByValueC omponentXS : IComponent, IServiceProvide r
{
// Fields
[NonSerialized]
private static readonly object EventDisposed;
[NonSerialized]
private EventHandlerLis t events;
[NonSerialized]
private ISite site;
/// <summary>
/// Initializes a new instance of the MarshalByValueC omponentXS
class.
/// </summary>
static MarshalByValueC omponentXS()
{
MarshalByValueC omponentXS.Even tDisposed = new object();
}
/// <summary>
/// Initializes a new instance of the MarshalByValueC omponentXS
class.
/// </summary>
public MarshalByValueC omponentXS()
{
}
/// <summary>
/// This member overrides Object.Finalize .
/// </summary>
~MarshalByValue ComponentXS()
{
this.Dispose(fa lse);
}
/// <summary>
/// Releases all resources used by the MarshalByValueC omponentXS.
/// </summary>
public void Dispose()
{
this.Dispose(tr ue);
GC.SuppressFina lize(this);
}
/// <summary>
/// Releases the unmanaged resources used by the
MarshalByValueC omponentXS and optionally releases the managed resources.
/// </summary>
/// <param name="disposing ">true to release both managed and
unmanaged resources; false to release only unmanaged resources. </param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
lock (this)
{
if ((this.site != null) && (this.site.Cont ainer !=
null))
{
this.site.Conta iner.Remove(thi s);
}
if (this.events != null)
{
EventHandler handler1 = (EventHandler)
this.events[MarshalByValueC omponentXS.Even tDisposed];
if (handler1 == null)
{
return;
}
handler1(this, EventArgs.Empty );
}
}
}
}
/// <summary>
/// Gets the implementer of the IServiceProvide r.
/// </summary>
/// <param name="serviceTy pe">A Type that represents the type of
service you want. </param>
/// <returns>An Object that represents the implementer of the
IServiceProvide r.</returns>
public virtual object GetService(Type serviceType)
{
if (this.site != null)
{
return this.site.GetSe rvice(serviceTy pe);
}
return null;
}
/// <summary>
/// This member overrides Object.ToString .
/// </summary>
/// <returns>A String that represents the current Object.</returns>
public override string ToString()
{
ISite site1 = this.site;
if (site1 != null)
{
return (site1.Name + " [" + base.GetType(). FullName + "]");
}
return base.GetType(). FullName;
}
/// <summary>
/// Gets the container for the component.
/// </summary>
[XmlIgnore, SoapIgnore,
DesignerSeriali zationVisibilit y(DesignerSeria lizationVisibil ity.Hidden),
Browsable(false )]
public virtual IContainer Container
{
get
{
ISite site1 = this.site;
if (site1 != null)
{
return site1.Container ;
}
return null;
}
}
/// <summary>
/// Gets a value indicating whether the component is currently in
design mode.
/// </summary>
[XmlIgnore, SoapIgnore,
DesignerSeriali zationVisibilit y(DesignerSeria lizationVisibil ity.Hidden),
Browsable(false )]
public virtual bool DesignMode
{
get
{
ISite site1 = this.site;
if (site1 != null)
{
return site1.DesignMod e;
}
return false;
}
}
/// <summary>
/// Gets or sets the site of the component.
/// </summary>
[XmlIgnore, SoapIgnore, Browsable(false ),
DesignerSeriali zationVisibilit y(DesignerSeria lizationVisibil ity.Hidden)]
public virtual ISite Site
{
get
{
return this.site;
}
set
{
this.site = value;
}
}
/// <summary>
/// Gets the list of event handlers that are attached to this
component.
/// </summary>
protected EventHandlerLis t Events
{
get
{
if (this.events == null)
{
this.events = new EventHandlerLis t();
}
return this.events;
}
}
/// <summary>
/// Adds an event handler to listen to the Disposed event on the
component
/// </summary>
public event EventHandler Disposed
{
add
{
this.Events.Add Handler(Marshal ByValueComponen tXS.EventDispos ed,
value);
}
remove
{
this.Events.Rem oveHandler(Mars halByValueCompo nentXS.EventDis posed,
value);
}
}
}
}
-------------------------
Collection base:
-------------------------
using System;
using System.Collecti ons;
using System.Componen tModel;
using System.Runtime. Serialization;
using System.Xml.Seri alization;
namespace Project.Model.T ypes
{
/// <summary>
/// Base class for collection implementations .
/// </summary>
[Serializable, XmlRoot("BizObj CollectionBase" )]
public class BizObjCollectio nBase : MarshalByValueC omponentXS,
ICollection, IList, ISerializable
{
#region Private members
/// <summary>
/// The ArrayList to store the components in
/// </summary>
private ArrayList _list = new ArrayList();
#endregion
#region Private properties
#region Implicit IList implementation
/// <summary>
/// Gets or sets the element at the specified index.
/// </summary>
object IList.this[ int index ]
{
get
{
return List[index];
}
set
{
OnSet(index, List[index], value);
List[index] = value;
}
}
public BizObjBase this[ int index ]
{
get
{
return (BizObjBase)Lis t[index];
}
set
{
OnSet(index, List[index], value);
List[index] = value;
}
}
bool IList.IsReadOnl y
{
get
{
return List.IsReadOnly ;
}
}
bool IList.IsFixedSi ze
{
get
{
return List.IsFixedSiz e;
}
}
#endregion
#region Implicit ICollection implementation
object ICollection.Syn cRoot
{
get
{
return this;
}
}
bool ICollection.IsS ynchronized
{
get
{
return false;
}
}
#endregion
#endregion
#region Protected properties
/// <summary>
/// Gets an IList containing the list of elements in the
SystemComponent Collection instance.
/// </summary>
protected IList List
{
get
{
return (IList)_list;
}
}
/// <summary>
/// Gets an ArrayList containing the list of elements in the
CollectionBase instance.
/// </summary>
protected ArrayList InnerList
{
get
{
return _list;
}
}
#endregion
#region Public properties
#region ICollection implementation
/// <summary>
/// Copies the WebCompetenceCo llection or a portion of it to a
one-dimensional array.
/// </summary>
/// <param name="array">Th e one-dimensional Array that is the
destination of the elements copied from the WebCompetenceCo llection. The
Array must have zero-based indexing. </param>
/// <param name="index">Th e zero-based index in array at which
copying begins. </param>
public void CopyTo(Array array, int index)
{
List.CopyTo(arr ay, index);
}
/// <summary>
/// Gets the number of elements actually contained in the
WebCompetenceCo llection.
/// </summary>
public virtual int Count
{
get
{
return List.Count;
}
}
#endregion
#endregion
#region Private methods
#region Implicit IList implementation
int IList.Add(objec t value)
{
OnValidate(valu e);
return List.Add(value) ;
}
public int Add(BizObjBase value)
{
OnValidate(valu e);
return List.Add(value) ;
}
bool IList.Contains( object value)
{
return List.Contains(v alue);
}
int IList.IndexOf(o bject value)
{
return List.IndexOf(va lue);
}
void IList.Insert(in t index, object value)
{
OnInsert(index, value);
List.Insert(ind ex, value);
}
void IList.Remove(ob ject value)
{
OnRemove(List.I ndexOf(value), value);
List.Remove(val ue);
}
#endregion
#endregion
#region Public methods
#region IList implementation
/// <summary>
/// Removes all elements from the WebCompetenceCo llection
/// </summary>
public void Clear()
{
List.Clear();
}
/// <summary>
/// Removes the element at the specified index of the
WebCompetenceCo llection
/// </summary>
/// <param name="index">Th e zero-based index of the element to
remove. </param>
public void RemoveAt(int index)
{
List.RemoveAt(i ndex);
}
#endregion
/// <summary>
/// Returns an enumerator that can iterate through the
WebCompetenceCo llection
/// </summary>
/// <returns>Return s an enumerator for the entire
WebCompetenceCo llection</returns>
public IEnumerator GetEnumerator()
{
return List.GetEnumera tor();
}
#endregion
#region Public delegates and events
/// <summary>
/// Represents a method that is called after a collection has
validated added or changed data.
/// </summary>
public delegate void ValidationCompl eteEventHandler ( object value );
/// <summary>
/// Occurs after the collection has added or validated data. Might
not be fired by all collection implementations .
/// </summary>
public virtual event ValidationCompl eteEventHandler
OnValidationCom plete;
/// <summary>
/// Validates the type of the attempted inserted object.
/// </summary>
/// <param name="index">Th e index of the added object.</param>
/// <param name="value">Th e value of the added object.</param>
protected virtual void OnInsert( int index, Object value )
{
}
/// <summary>
/// Validates the type of an attempted removed object.
/// </summary>
/// <param name="index">Th e index of the removed object.</param>
/// <param name="value">Th e value of the removed object.</param>
protected virtual void OnRemove( int index, Object value )
{
}
/// <summary>
/// Validates the type of an attempted set object.
/// </summary>
/// <param name="index">Th e index of the set object.</param>
/// <param name="oldValue" >The value of the old object.</param>
/// <param name="newValue" >The value of the new object.</param>
protected virtual void OnSet( int index, Object oldValue, Object
newValue )
{
}
/// <summary>
/// Validates the type of the value when validated.
/// </summary>
/// <param name="value">Th e value to validate.</param>
protected virtual void OnValidate( Object value )
{
if (OnValidationCo mplete != null)
OnValidationCom plete(value);
}
#endregion
#region Constructors
/// <summary>
/// Protected constructor, class must be inherited.
/// </summary>
public BizObjCollectio nBase()
{
}
/// <summary>
/// Constructor used when deserializing.
/// </summary>
/// <param name="info">The SerializationIn fo object</param>
/// <param name="context"> The StreamingContex t object</param>
protected BizObjCollectio nBase(Serializa tionInfo info,
StreamingContex t context)
{
int count = info.GetInt32(" _count");
for(int i = 0; i<count; i++)
List.Add((BizOb jBase)info.GetV alue("_item" + i,
typeof(BizObjBa se)));
}
#endregion
#region Serialization
/// <summary>
/// Serializes the collection
/// </summary>
/// <param name="info">The info</param>
/// <param name="context"> The context</param>
public virtual void GetObjectData(S erializationInf o info,
StreamingContex t context)
{
info.AddValue(" _count", Count);
for(int i = 0; i<Count; i++)
info.AddValue(" _item" + i.ToString(), (BizObjBase)Lis t[i]);
}
#endregion
}
}
---------------
Business object base:
---------------
using System;
using System.Componen tModel;
using System.Reflecti on;
using System.Runtime. Serialization;
using System.Security .Permissions;
using System.Xml.Seri alization;
namespace Project.Model.T ypes
{
/// <summary>
/// The base class of all Business Objects
/// </summary>
[Serializable, XmlRoot]
public class BizObjBase : MarshalByValueC omponentXS, ISerializable
{
/// <summary>
/// Indicates the persistion state of the object.
/// </summary>
/// <remarks>
/// The default value of _state is StateEnum.New.< br/>
/// All property setters in derived classes should set _state to
Updated
/// so persisting is done properly.
/// </remarks>
protected StateEnum _state = StateEnum.New;
/// <summary>
/// Gets or sets the persistion state of the object.
/// </summary>
[XmlElement, DefaultValue(St ateEnum.New)]
public virtual StateEnum State
{
get
{
return _state;
}
set
{
_state = value;
}
}
/// <summary>
/// Initializes a new instance of the BizObjBase class
/// </summary>
public BizObjBase()
{
}
/// <summary>
/// Initializes a new instance of the BizObjBase when deserialized
by a Serializer.
/// </summary>
/// <param name="info">The SerializationIn fo to fetch data from.
</param>
/// <param name="context"> The context of the operation</param>
protected BizObjBase(Seri alizationInfo info, StreamingContex t
context)
{
_state = (StateEnum)info .GetValue("_sta te", typeof(StateEnu m));
}
/// <summary>
/// If state is Unchanged, IfUpdatingSetSt ate compares the new value
with the original value, and sets State to StateEnum.Updat ed if the values
differ.
/// </summary>
/// <param name="newValue" >The new value attempted.</param>
/// <param name="originalV alue">The original value of the
property</param>
protected void IfUpdatingSetSt ate(object newValue, object
originalValue)
{
if (State == StateEnum.Uncha nged)
{
if (newValue == null && originalValue == null)
return;
if (
(newValue == null && originalValue != null)
||
(!newValue.Equa ls(originalValu e))
)
State = StateEnum.Updat ed;
}
}
/// <summary>
/// Compares the fields of two objects.
/// </summary>
/// <param name="obj">The object to compare with</param>
/// <returns>%tru e% if the objects are equal; otherwise
%false%</returns>
public override bool Equals(object obj)
{
Type thisType = obj.GetType();
foreach(FieldIn fo fieldInfo in
thisType.GetFie lds(BindingFlag s.NonPublic))
if (fieldInfo.GetV alue(obj) != fieldInfo.GetVa lue(this))
return false;
return true;
}
/// <summary>
/// Serves as a hash function for a particular type, suitable for
use in hashing algorithms and data structures like a hash table.
/// </summary>
/// <returns>
/// A hash code for the current Object.<br/>
/// If the current object has a non public field named _id, the
value of that field is used, else the base.GetHashCod e() return value is
used.
/// </returns>
public override int GetHashCode()
{
Type thisType = this.GetType();
FieldInfo field = thisType.GetFie ld("_id",
BindingFlags.No nPublic);
if (field != null && field.FieldType == typeof(Int32))
return Convert.ToInt32 (field.GetValue (this));
else
return base.GetHashCod e ();
}
/// <summary>
/// Compares the identity of two objects.
/// </summary>
/// <param name="obj">The object to compare with.</param>
/// <returns>%tru e% if the objects have the same identity; otherwise
%false%</returns>
public bool RefEquals(objec t obj)
{
return base.Equals(obj );
}
/// <summary>
/// Releases the resources used by the Component and optionally
releases the managed resources.
/// </summary>
/// <param name="disposing ">true to release both managed and
unmanaged resources; false to release only unmanaged resources. </param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
// Dispose unmanaged resources
}
// Disposed managed
// Base dispose
base.Dispose(di sposing);
}
/// <summary>
/// Initializes the components in BizObjBase
/// </summary>
private void InitializeCompo nent()
{
}
/// <summary>
/// Populates a SerializationIn fo with the data needed to serialize
the target object.
/// </summary>
/// <remarks>
/// <font color="red">Pre liminary!!</font>
/// </remarks>
/// <param name="info">The SerializationIn fo to populate with data.
</param>
/// <param name="context"> The destination (see StreamingContex t) for
this serialization. </param>
[SecurityPermiss ionAttribute(Se curityAction.De mand,Serializat ionFormatter=tr ue)]
public virtual void GetObjectData(S erializationInf o info,
StreamingContex t context)
{
info.AddValue(" _state", _state);
}
}
}
---------------------
StateEnum enumeration used in the BizObjBase:
---------------------
namespace Project.Model.T ypes
{
/// <summary>
/// Specifies the objects current persistation state
/// </summary>
public enum StateEnum
{
/// <summary>
/// The object is unchanged since loaded.
/// </summary>
Unchanged = 0,
/// <summary>
/// The object has never been persisted.
/// </summary>
New = 1,
/// <summary>
/// The object has changed since loaded.
/// </summary>
Updated = 2,
/// <summary>
/// The object is marked for deletion.
/// </summary>
Deleted = 3
}
}
-----------
Here's a program that fails:
-----------
using System;
using System.Xml.Seri alization;
using Project.Model.T ypes;
namespace Project
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
XmlSerializer colSerializer = new
XmlSerializer(t ypeof(BizObjCol lectionBase));
}
}
}
----------
Hope you're able to find something :)
L-E
"Kevin Yu [MSFT]" <v-****@online.mic rosoft.com> wrote in message
news:A8******** ******@TK2MSFTN GXA01.phx.gbl.. .
Hi L-E,
Could you post the definition of the base class here, so that I can try to
repro the problem?
Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."