Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / Host / Serialization / DesignerSerializationManager.cs / 1 / DesignerSerializationManager.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.ComponentModel.Design.Serialization {
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Design;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
///
///
/// This object is a complete implementation of IDesignerSerializationManager. It can be used to
/// begin the serialization / deserialization process for any serialization scheme that utilizes
/// IDesignerSerializationManager.
///
public class DesignerSerializationManager : IDesignerSerializationManager {
private IServiceProvider provider;
private ITypeResolutionService typeResolver;
private bool searchedTypeResolver;
private bool recycleInstances;
private bool validateRecycledTypes;
private bool preserveNames;
private IContainer container;
private IDisposable session;
private ResolveNameEventHandler resolveNameEventHandler;
private EventHandler serializationCompleteEventHandler;
private EventHandler sessionCreatedEventHandler;
private EventHandler sessionDisposedEventHandler;
private ArrayList designerSerializationProviders;
private Hashtable defaultProviderTable;
private Hashtable instancesByName;
private Hashtable namesByInstance;
private Hashtable serializers;
private ArrayList errorList;
private ContextStack contextStack;
private PropertyDescriptorCollection properties;
private object propertyProvider;
///
///
/// Creates a new serialization manager.
///
public DesignerSerializationManager() {
this.preserveNames = true;
this.validateRecycledTypes = true;
}
///
///
/// Creates a new serialization manager.
///
public DesignerSerializationManager(IServiceProvider provider) {
if (provider == null) {
throw new ArgumentNullException("provider");
}
this.provider = provider;
this.preserveNames = true;
this.validateRecycledTypes = true;
}
///
///
/// Provides access to the container that components will
/// be added to. The default implementation searches
/// for IDesignerHost in the service provider and uses
/// its container if it exists.
///
public IContainer Container {
get {
if (container == null) {
IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host != null) {
container = host.Container;
}
}
return container;
}
set {
CheckNoSession();
container = value;
}
}
///
///
/// This retrieves the collection of errors that have
/// been reported to the serialization manager.
/// Additionaly, new errors can be added to the list
/// by accessing this property.
///
public IList Errors {
get {
CheckSession();
if (errorList == null) {
errorList = new ArrayList();
}
return errorList;
}
}
///
///
/// This property determines the behavior of the CreateInstance method. If true, CreateInstance will
/// pass the given component name. If false, CreateInstance will check for the presence
/// of the given name in the container. If it does not exist, it will use the given name.
/// If it does exist, it will pass a null value as the name of a component when adding
/// it to the container, thereby giving it a new name.
/// This second variation is useful for implementing a serializer that always duplicates objects, rather than
/// assuming those objects do not exist. Paste commands often use this type of serializer.
/// The default value of this property is true.
///
public bool PreserveNames {
get {
return preserveNames;
}
set {
CheckNoSession();
preserveNames = value;
}
}
///
///
/// This property returns the object that should be used to provide properties to the serialization manager's Propeties property. This object's
/// public properties will be inspected and wrapped in new property descriptors that have a target object of the serialization manager.
///
public object PropertyProvider {
get {
return propertyProvider;
}
set {
if (propertyProvider != value) {
propertyProvider = value;
properties = null;
}
}
}
///
///
/// This property determines the behavior of the CreateInstance method. If false, CreateInstance will always create a new instance
/// of an object. If true, CreateInstance will first search the nametable and container for an object of the same name. If such
/// an object exists and is of the same type, CreateInstance will return the existing object instance. This second variation is
/// useful for implemeting a serializer that applies serialization state to an existing set of objects, rather than always creating
/// a new tree. Undo often uses this type of serializer.
/// The default value of this property is false.
///
public bool RecycleInstances {
get {
return recycleInstances;
}
set {
CheckNoSession();
recycleInstances = value;
}
}
///
///
/// This property determines the behavior of the CreateInstance method and only applies if RecyleInstances is true. If true, and
/// an existing instance is found for the given name, it will only be returned if the two types match. If false, the instance
/// will be returned even if the two types do not match. This is useful for "morphing" one type of object to another if they have
/// similar properties but share no common parent or interface.
/// The default value of this property is true.
///
public bool ValidateRecycledTypes {
get {
return validateRecycledTypes;
}
set {
CheckNoSession();
validateRecycledTypes = value;
}
}
///
///
/// Event that is raised when a session is created.
///
public event EventHandler SessionCreated {
add {
sessionCreatedEventHandler += value;
}
remove {
sessionCreatedEventHandler -= value;
}
}
///
///
/// Event that is raised when a session is disposed.
///
public event EventHandler SessionDisposed {
add {
sessionDisposedEventHandler += value;
}
remove {
sessionDisposedEventHandler -= value;
}
}
///
/// Used to verify that no session is active. If there is, this method
/// throws.
///
private void CheckNoSession() {
if (session != null) {
throw new InvalidOperationException(SR.GetString(SR.SerializationManagerWithinSession));
}
}
///
/// Used to verify that there is an open session. If there isn't, this method
/// throws.
///
private void CheckSession() {
if (session == null) {
throw new InvalidOperationException(SR.GetString(SR.SerializationManagerNoSession));
}
}
///
///
/// Creates an instance of the specified type. The default
/// implementation will create the object. If the object implements
/// IComponent and only requires an empty or IContainer style
/// constructor, this will search for IDesignerHost and create
/// through the host. Otherwise it will use reflection. If
/// addToContainer is true, this will add to the container
/// using this class's Conainer property, using the
/// name provided if it is not null.
///
protected virtual object CreateInstance(Type type, ICollection arguments, string name, bool addToContainer) {
object[] argArray = null;
if (arguments != null && arguments.Count > 0) {
argArray = new object[arguments.Count];
arguments.CopyTo(argArray, 0);
}
object instance = null;
// If we have been asked to recycle instances, look in our nametable
// and container first for an object matching this name and type. If
// we find it, we will use it.
//
if (RecycleInstances && name != null) {
if (instancesByName != null) {
instance = instancesByName[name];
}
if (instance == null && addToContainer && Container != null) {
instance = Container.Components[name];
}
if (instance != null && ValidateRecycledTypes && instance.GetType() != type) {
// We got an instance, but it is not of the correct type. We
// don't allow this.
instance = null;
}
}
// If the stars properly align, we will let the designer host create the component.
// For this to happen, the following criteria must hold true:
//
// 1. The type must be a component.
// 2. addToContainer is true.
// 3. The type has a null ctor or an IContainer ctor.
// 4. The host is available and its container matches our container.
//
// The reason for this is that if we went through activator,
// and if the object already specified a constructor that took an IContainer, our
// deserialization mechanism would equate the container to the designer host. This
// is the correct thing to do, but it has the side effect of adding the compnent
// to the designer host twice -- once with a default name, and a second time with
// the name we provide. This equates to a component rename, which isn't cheap,
// so we don't want to do it when we load each and every component.
//
if (instance == null && addToContainer && typeof(IComponent).IsAssignableFrom(type) && (argArray == null || argArray.Length == 0 ||( argArray.Length == 1 && argArray[0] == Container))) {
IDesignerHost host = GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host != null && host.Container == Container) {
bool ignoreName = false;
if (!PreserveNames && name != null) {
// Check if this name exists in the container. If so,
// don't use it.
//
if (Container.Components[name] != null) {
ignoreName = true;
}
}
if (name == null || ignoreName) {
instance = host.CreateComponent(type);
}
else {
instance = host.CreateComponent(type, name);
}
}
}
// Default case, just create the component through reflection.
//
if (instance == null) {
try {
try {
// First, just try to create the object directly with the arguments. generaly this
// should work.
//
instance = TypeDescriptor.CreateInstance(provider, type, null, argArray);
}
catch (MissingMethodException mmex) {
// okay, the create failed because the argArray didn't match the types of ctors that
// are available. don't panic, we're tough. we'll try to coerce the types to match
// the ctor.
//
Type[] types = new Type[argArray.Length];
// first, get the types of the arguments we've got.
//
for(int index = 0; index < argArray.Length; index++) {
if (argArray[index] != null) {
types[index] = argArray[index].GetType();
}
}
object[] tempArgs = new object[argArray.Length];
// now, walk the public ctors looking for one to
// invoke here with the arguments we have.
//
foreach(ConstructorInfo ci in TypeDescriptor.GetReflectionType(type).GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance)) {
ParameterInfo[] pi = ci.GetParameters();
// obviously the count has to match
//
if (pi != null && pi.Length == types.Length) {
bool match = true;
// now walk every type of argument and compare it to
// the corresponding argument. if it matches up exactly or is a derived type, great.
// otherwise, we'll try to use IConvertible to make it into the right thing.
//
for (int t = 0; t < types.Length; t++) {
if (types[t] == null || pi[t].ParameterType.IsAssignableFrom(types[t])) {
tempArgs[t] = argArray[t];
continue;
}
if (argArray[t] is IConvertible) {
try {
// try the IConvertible route. If it works, we'll call it a match
// for this parameter and continue on.
//
tempArgs[t] = ((IConvertible)argArray[t]).ToType(pi[t].ParameterType, null);
continue;
}
catch (InvalidCastException) {
}
}
match = false;
break;
}
// all of the parameters were converted or matched, so try the creation again.
// if that works, we're in the money.
//
if (match) {
instance = TypeDescriptor.CreateInstance(provider, type, null, tempArgs);
break;
}
}
}
// we still failed...rethrow the original exception.
//
if (instance == null) {
throw mmex;
}
}
}
catch(MissingMethodException) {
StringBuilder argTypes = new StringBuilder();
foreach (object o in argArray) {
if (argTypes.Length > 0) {
argTypes.Append(", ");
}
if (o != null) {
argTypes.Append(o.GetType().Name);
}
else {
argTypes.Append("null");
}
}
Exception ex = new SerializationException(SR.GetString(SR.SerializationManagerNoMatchingCtor, type.FullName, argTypes.ToString()));
ex.HelpLink = SR.SerializationManagerNoMatchingCtor;
throw ex;
}
// Now, if we needed to add this to the container, do so .
//
if (addToContainer && instance is IComponent && Container != null) {
bool ignoreName = false;
if (!PreserveNames && name != null) {
// Check if this name exists in the container. If so,
// don't use it.
//
if (Container.Components[name] != null) {
ignoreName = true;
}
}
if (name == null || ignoreName) {
Container.Add((IComponent)instance);
}
else {
Container.Add((IComponent)instance, name);
}
}
}
return instance;
}
///
///
/// Creates a new serialization session. Most data within
/// the serialization manager is transient and only lives
/// for the life of a serialization session. When a session
/// is disposed, serialization is considered to be complete
/// and this transient state is cleared. This allows a
/// single instance of a serialization manager to be used
/// to serialize multiple object trees. Some state, including
/// the service provider and any custom serialization providers
/// that were added to the serialization manager, span sessions.
///
public IDisposable CreateSession() {
if (session != null) {
throw new InvalidOperationException(SR.GetString(SR.SerializationManagerAreadyInSession));
}
session = new SerializationSession(this);
OnSessionCreated(EventArgs.Empty);
return session;
}
///
///
/// This retrieves the serializer for the given object type.
/// You can request what type of serializer you would like.
/// It is possible for this method to return null if there
/// is no serializer of the requested type.
///
public object GetSerializer(Type objectType, Type serializerType) {
if (serializerType == null) {
throw new ArgumentNullException("serializerType");
}
object serializer = null;
if (objectType != null) {
if (serializers != null) {
// I don't double hash here. It will be a very rare day where
// multiple types of serializers will be used in the same scheme.
// We still handle it, but we just don't cache.
//
serializer = serializers[objectType];
if (serializer != null && !serializerType.IsAssignableFrom(serializer.GetType())) {
serializer = null;
}
}
// Now actually look in the type's metadata.
//
if (serializer == null) {
AttributeCollection attributes = TypeDescriptor.GetAttributes(objectType);
foreach(Attribute attr in attributes) {
if (attr is DesignerSerializerAttribute) {
DesignerSerializerAttribute da = (DesignerSerializerAttribute)attr;
string typeName = da.SerializerBaseTypeName;
// This serializer must support the correct base type or we're not interested.
//
if (typeName != null) {
Type baseType = GetType(typeName);
if (baseType == serializerType && da.SerializerTypeName != null && da.SerializerTypeName.Length > 0) {
Type type = GetType(da.SerializerTypeName);
Debug.Assert(type != null, "Type " + objectType.FullName + " has a serializer that we couldn't bind to: " + da.SerializerTypeName);
if (type != null) {
serializer = Activator.CreateInstance(type, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null);
break;
}
}
}
}
}
// And stash this little guy for later, but only if we're in a session.
// If we're outside of a session this should still be useable for resolving
// serializers, but we don't cache them.
//
if (serializer != null && session != null)
{
if (serializers == null)
{
serializers = new Hashtable();
}
serializers[objectType] = serializer;
}
}
}
// Check for a default serialization provider
//
if (defaultProviderTable == null || !defaultProviderTable.ContainsKey(serializerType)) {
Type defaultSerializerType = null;
DefaultSerializationProviderAttribute a = (DefaultSerializationProviderAttribute)TypeDescriptor.GetAttributes(serializerType)[typeof(DefaultSerializationProviderAttribute)];
if (a != null) {
defaultSerializerType = GetType(a.ProviderTypeName);
if (defaultSerializerType != null && typeof(IDesignerSerializationProvider).IsAssignableFrom(defaultSerializerType)) {
IDesignerSerializationProvider p = (IDesignerSerializationProvider)Activator.CreateInstance(
defaultSerializerType,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance,
null, null, null);
((IDesignerSerializationManager)this).AddSerializationProvider(p);
}
}
if (defaultProviderTable == null) {
defaultProviderTable = new Hashtable();
}
defaultProviderTable[serializerType] = defaultSerializerType;
}
// Designer serialization providers can override our metadata discovery.
// We loop until we reach steady state. This breaks order dependencies
// by allowing all providers a chance to party on each other's serializers.
//
if (designerSerializationProviders != null) {
bool continueLoop = true;
for(int i = 0; continueLoop && i < designerSerializationProviders.Count; i++) {
continueLoop = false;
foreach(IDesignerSerializationProvider provider in designerSerializationProviders) {
object newSerializer = provider.GetSerializer(this, serializer, objectType, serializerType);
if (newSerializer != null) {
continueLoop = (serializer != newSerializer);
serializer = newSerializer;
}
}
}
}
return serializer;
}
///
///
/// Provides access to the underlying IServiceProvider
///
protected virtual object GetService(Type serviceType) {
if (serviceType == typeof(IContainer)) {
return Container;
}
if (provider != null) {
return provider.GetService(serviceType);
}
return null;
}
///
///
/// Retrives the type for the given name using the type resolution
/// service, if available.
///
protected virtual Type GetType(string typeName) {
if (typeResolver == null && !searchedTypeResolver) {
typeResolver = GetService(typeof(ITypeResolutionService)) as ITypeResolutionService;
searchedTypeResolver = true;
}
if (typeResolver == null) {
return Type.GetType(typeName);
}
else {
return typeResolver.GetType(typeName);
}
}
///
///
/// Event that is raised when a name needs to be resolved to an object instance..
///
protected virtual void OnResolveName(ResolveNameEventArgs e) {
if (resolveNameEventHandler != null) {
resolveNameEventHandler(this, e);
}
}
///
///
/// Event that is raised when a session is created.
///
protected virtual void OnSessionCreated(EventArgs e) {
if (sessionCreatedEventHandler != null) {
sessionCreatedEventHandler(this, e);
}
}
///
///
/// Event that is raised when a session is disposed.
///
protected virtual void OnSessionDisposed(EventArgs e) {
try {
try {
if (sessionDisposedEventHandler != null) {
sessionDisposedEventHandler(this, e);
}
}
finally {
if (serializationCompleteEventHandler != null) {
serializationCompleteEventHandler(this, EventArgs.Empty);
}
}
}
finally {
resolveNameEventHandler = null;
serializationCompleteEventHandler = null;
instancesByName = null;
namesByInstance = null;
serializers = null;
contextStack = null;
errorList = null;
session = null;
}
}
///
///
/// This method takes a property that is owned by the
/// given owner, and it wraps them in new property that
/// is owned by the serialization manager.
///
private PropertyDescriptor WrapProperty(PropertyDescriptor property, object owner) {
if (property == null) {
throw new ArgumentNullException("property");
}
// owner can be null for static properties.
return new WrappedPropertyDescriptor(property, owner);
}
///
///
/// The Context property provides a user-defined storage area
/// implemented as a stack. This storage area is a useful way
/// to provide communication across serializers, as serialization
/// is a generally hierarchial process.
///
ContextStack IDesignerSerializationManager.Context {
get {
if (contextStack == null) {
CheckSession();
contextStack = new ContextStack();
}
return contextStack;
}
}
///
///
/// The Properties property provides a set of custom properties
/// the serialization manager may surface. The set of properties
/// exposed here is defined by the implementor of
/// IDesignerSerializationManager.
///
PropertyDescriptorCollection IDesignerSerializationManager.Properties {
get {
if (properties == null) {
object propObject = PropertyProvider;
PropertyDescriptor[] propArray;
if (propObject == null) {
propArray = new PropertyDescriptor[0];
}
else {
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(propObject);
propArray = new PropertyDescriptor[props.Count];
for (int i = 0; i < propArray.Length; i++) {
propArray[i] = WrapProperty(props[i], propObject);
}
}
properties = new PropertyDescriptorCollection(propArray);
}
return properties;
}
}
///
///
/// ResolveName event. This event
/// is raised when GetName is called, but the name is not found
/// in the serialization manager's name table. It provides a
/// way for a serializer to demand-create an object so the serializer
/// does not have to order object creation by dependency. This
/// delegate is cleared immediately after serialization or deserialization
/// is complete.
///
event ResolveNameEventHandler IDesignerSerializationManager.ResolveName {
add {
CheckSession();
resolveNameEventHandler += value;
}
remove {
resolveNameEventHandler -= value;
}
}
///
///
/// This event is raised when serialization or deserialization
/// has been completed. Generally, serialization code should
/// be written to be stateless. Should some sort of state
/// be necessary to maintain, a serializer can listen to
/// this event to know when that state should be cleared.
/// An example of this is if a serializer needs to write
/// to another file, such as a resource file. In this case
/// it would be inefficient to design the serializer
/// to close the file when finished because serialization of
/// an object graph generally requires several serializers.
/// The resource file would be opened and closed many times.
/// Instead, the resource file could be accessed through
/// an object that listened to the SerializationComplete
/// event, and that object could close the resource file
/// at the end of serialization.
///
event EventHandler IDesignerSerializationManager.SerializationComplete {
add {
CheckSession();
serializationCompleteEventHandler += value;
}
remove {
serializationCompleteEventHandler -= value;
}
}
///
///
/// This method adds a custom serialization provider to the
/// serialization manager. A custom serialization provider will
/// get the opportunity to return a serializer for a data type
/// before the serialization manager looks in the type's
/// metadata.
///
void IDesignerSerializationManager.AddSerializationProvider(IDesignerSerializationProvider provider) {
if (designerSerializationProviders == null) {
designerSerializationProviders = new ArrayList();
}
if (!designerSerializationProviders.Contains(provider)) {
designerSerializationProviders.Add(provider);
}
}
///
///
/// Creates an instance of the given type and adds it to a collection
/// of named instances. Objects that implement IComponent will be
/// added to the design time container if addToContainer is true.
///
object IDesignerSerializationManager.CreateInstance(Type type, ICollection arguments, string name, bool addToContainer) {
CheckSession();
// If we were given a name verify that the name doesn't
// already exist. We do not verify uniqueness in our parent container
// here because CreateInstance may modify the name for us. If it
// didn't, the container itself will throw, so we're covered.
//
if (name != null) {
if (instancesByName != null && instancesByName.ContainsKey(name)) {
Exception ex = new SerializationException(SR.GetString(SR.SerializationManagerDuplicateComponentDecl, name));
ex.HelpLink = SR.SerializationManagerDuplicateComponentDecl;
throw ex;
}
}
object instance = CreateInstance(type, arguments, name, addToContainer);
// If we have a name save it into our own nametable. We
// do this even for objects that were added to the container, because
// containers reserve the right to change the name in case of collision.
// Changing the name is fine, but it would be very difficult to map
// that to the rest of the serializers. Instead, we keep the old
// name in our local nametable so a serializer can ask for an object
// by the old name. Because the old nametable is searched first, the
// old name is preserved. Note that this technique is ONLY valid
// if RecycleInstances is false. If it is true, we cannot store
// in the old nametable because it would be possible to fetch
// the wrong value from the container. Consider a request for
// "button1' that results in the creation of an object in the
// container called "button2" due to a collision. If a request
// later came in for "button2", the wrong object would be returned
// because RecycleInstances checks the container first. So, it
// is only safe to store the local value if RecycleInstances is false.
// When RecycleInstances is true if there was a collision the object
// would have been returned, so there is no need to store locally.
//
if (name != null // If we were given a name
&& (!(instance is IComponent) // And it's not an icomponent
|| !RecycleInstances)) { // Or it is an icomponent but recycle instances is turned off
if (instancesByName == null) {
instancesByName = new Hashtable();
namesByInstance = new Hashtable(new ReferenceComparer());
}
instancesByName[name] = instance;
namesByInstance[instance] = name;
}
return instance;
}
///
///
/// Retrieves an instance of a created object of the given name, or
/// null if that object does not exist.
///
object IDesignerSerializationManager.GetInstance(string name) {
object instance = null;
if (name == null) {
throw new ArgumentNullException("name");
}
CheckSession();
// Check our local nametable first
//
if (instancesByName != null) {
instance = instancesByName[name];
}
if (instance == null && PreserveNames && Container != null) {
instance = Container.Components[name];
}
if (instance == null) {
ResolveNameEventArgs e = new ResolveNameEventArgs(name);
OnResolveName(e);
instance = e.Value;
}
return instance;
}
///
///
/// Retrieves a name for the specified object, or null if the object
/// has no name.
///
string IDesignerSerializationManager.GetName(object value) {
string name = null;
if (value == null) {
throw new ArgumentNullException("value");
}
CheckSession();
// Check our local nametable first
//
if (namesByInstance != null) {
name = (string)namesByInstance[value];
}
if (name == null && value is IComponent) {
ISite site = ((IComponent)value).Site;
if (site != null) {
INestedSite nestedSite = site as INestedSite;
if (nestedSite != null) {
name = nestedSite.FullName;
}
else {
name = site.Name;
}
}
}
return name;
}
///
///
/// Retrieves a serializer of the requested type for the given
/// object type.
///
object IDesignerSerializationManager.GetSerializer(Type objectType, Type serializerType) {
return GetSerializer(objectType, serializerType);
}
///
///
/// Retrieves a type of the given name.
///
Type IDesignerSerializationManager.GetType(string typeName) {
CheckSession();
Type t = null;
while (t == null) {
t = GetType(typeName);
if (t == null && typeName != null && typeName.Length > 0) {
int dotIndex = typeName.LastIndexOf('.');
if (dotIndex == -1 || dotIndex == typeName.Length - 1) {
break;
}
typeName = typeName.Substring(0, dotIndex) + "+" + typeName.Substring(dotIndex + 1, typeName.Length - dotIndex - 1);
}
}
return t;
}
///
///
/// Removes a previously added serialization provider.
///
void IDesignerSerializationManager.RemoveSerializationProvider(IDesignerSerializationProvider provider) {
if (designerSerializationProviders != null) {
designerSerializationProviders.Remove(provider);
}
}
///
///
/// Reports a non-fatal error in serialization. The serialization
/// manager may implement a logging scheme to alert the caller
/// to all non-fatal errors at once. If it doesn't, it should
/// immediately throw in this method, which should abort
/// serialization.
/// Serialization may continue after calling this function.
///
void IDesignerSerializationManager.ReportError(object errorInformation) {
CheckSession();
if (errorInformation != null) {
Errors.Add(errorInformation);
}
}
internal ArrayList SerializationProviders {
get {
return (designerSerializationProviders != null) ? designerSerializationProviders.Clone() as ArrayList : new ArrayList();
}
}
///
///
/// Provides a way to set the name of an existing object.
/// This is useful when it is necessary to create an
/// instance of an object without going through CreateInstance.
/// An exception will be thrown if you try to rename an existing
/// object or if you try to give a new object a name that
/// is already taken.
///
void IDesignerSerializationManager.SetName(object instance, string name) {
CheckSession();
if (instance == null) {
throw new ArgumentNullException("instance");
}
if (name == null) {
throw new ArgumentNullException("name");
}
if (instancesByName == null) {
instancesByName = new Hashtable();
namesByInstance = new Hashtable(new ReferenceComparer());
}
if (instancesByName[name] != null) {
throw new ArgumentException(SR.GetString(SR.SerializationManagerNameInUse, name));
}
if (namesByInstance[instance] != null) {
throw new ArgumentException(SR.GetString(SR.SerializationManagerObjectHasName, name, (string)namesByInstance[instance]));
}
instancesByName[name] = instance;
namesByInstance[instance] = name;
}
///
///
/// IServiceProvider implementation.
///
object IServiceProvider.GetService(Type serviceType) {
return GetService(serviceType);
}
///
/// Session object that implements IDisposable.
///
private sealed class SerializationSession : IDisposable {
private DesignerSerializationManager serializationManager;
internal SerializationSession(DesignerSerializationManager serializationManager) {
this.serializationManager = serializationManager;
}
public void Dispose() {
serializationManager.OnSessionDisposed(EventArgs.Empty);
}
}
///
/// A key comparer that can be passed to a hash table
/// to use object reference identity as the key comparision.
///
private sealed class ReferenceComparer : IEqualityComparer {
bool IEqualityComparer.Equals(object x, object y) {
return object.ReferenceEquals(x, y);
}
int IEqualityComparer.GetHashCode(object x) {
if (x != null) {
return x.GetHashCode();
}
return 0;
}
}
///
/// Wrapped property descriptor. Takes the given property
/// and wraps it in a new one that can take the designer serialization
/// manager as a target.
///
private sealed class WrappedPropertyDescriptor : PropertyDescriptor {
private object target;
private PropertyDescriptor property;
internal WrappedPropertyDescriptor(PropertyDescriptor property, object target) : base(property.Name, null) {
this.property = property;
this.target = target;
}
public override AttributeCollection Attributes {
get {
return property.Attributes;
}
}
public override Type ComponentType {
get {
return property.ComponentType;
}
}
public override bool IsReadOnly {
get {
return property.IsReadOnly;
}
}
public override Type PropertyType {
get {
return property.PropertyType;
}
}
public override bool CanResetValue(object component) {
return property.CanResetValue(target);
}
public override object GetValue(object component) {
return property.GetValue(target);
}
public override void ResetValue(object component) {
property.ResetValue(target);
}
public override void SetValue(object component, object value) {
property.SetValue(target, value);
}
public override bool ShouldSerializeValue(object component) {
return property.ShouldSerializeValue(target);
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MulticastDelegate.cs
- VisualTransition.cs
- WriteableOnDemandPackagePart.cs
- EntityRecordInfo.cs
- SqlProvider.cs
- EditorZoneBase.cs
- Hashtable.cs
- DurableOperationAttribute.cs
- TypeGeneratedEventArgs.cs
- infer.cs
- XPathNavigatorKeyComparer.cs
- UnsafeNativeMethods.cs
- DataGridLengthConverter.cs
- HitTestParameters.cs
- XmlTextReaderImpl.cs
- PhoneCall.cs
- StateInitializationDesigner.cs
- TextBoxRenderer.cs
- NameObjectCollectionBase.cs
- ButtonStandardAdapter.cs
- SafeRightsManagementSessionHandle.cs
- StatusBarDesigner.cs
- LinqDataSourceSelectEventArgs.cs
- XamlToRtfParser.cs
- XPathScanner.cs
- Vector3DValueSerializer.cs
- HttpWriter.cs
- dsa.cs
- UnitySerializationHolder.cs
- SoapIncludeAttribute.cs
- ReaderWriterLock.cs
- AbandonedMutexException.cs
- TransformerTypeCollection.cs
- MailWriter.cs
- WebDisplayNameAttribute.cs
- ValueHandle.cs
- SoapServerMethod.cs
- MSG.cs
- TdsParameterSetter.cs
- XsltArgumentList.cs
- NoResizeHandleGlyph.cs
- ContentTextAutomationPeer.cs
- returneventsaver.cs
- PerformanceCounterCategory.cs
- AsyncCompletedEventArgs.cs
- XLinq.cs
- Pkcs9Attribute.cs
- _ChunkParse.cs
- ActivityExecutionFilter.cs
- AssemblyHelper.cs
- OleDbDataAdapter.cs
- ApplicationTrust.cs
- MdiWindowListStrip.cs
- JapaneseLunisolarCalendar.cs
- DateTimeOffset.cs
- KeyPullup.cs
- ImageIndexConverter.cs
- NotifyIcon.cs
- PlanCompiler.cs
- EventNotify.cs
- SafeMarshalContext.cs
- AssociationType.cs
- CommentAction.cs
- FieldMetadata.cs
- ServiceOperationParameter.cs
- DesignerListAdapter.cs
- TypeToken.cs
- ProviderCollection.cs
- DataControlFieldHeaderCell.cs
- WindowsFormsLinkLabel.cs
- EmptyQuery.cs
- ConfigXmlElement.cs
- EntityDataSourceContextCreatedEventArgs.cs
- Sentence.cs
- FixedPageStructure.cs
- MailBnfHelper.cs
- AssemblyBuilderData.cs
- EdmPropertyAttribute.cs
- AbandonedMutexException.cs
- NavigationWindow.cs
- DependencyObject.cs
- DbProviderConfigurationHandler.cs
- SystemNetHelpers.cs
- DrawingCollection.cs
- Helpers.cs
- XmlNodeChangedEventManager.cs
- CodeCatchClause.cs
- ObjectTag.cs
- TextEditorCharacters.cs
- Content.cs
- ExpressionBuilderContext.cs
- PageAsyncTaskManager.cs
- TripleDESCryptoServiceProvider.cs
- ZipIOCentralDirectoryBlock.cs
- OpenFileDialog.cs
- LinqDataSourceUpdateEventArgs.cs
- DrawingCollection.cs
- MasterPageCodeDomTreeGenerator.cs
- StreamGeometry.cs
- Int32Collection.cs