Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / CompMod / System / ComponentModel / Design / Serialization / ComponentCodeDomSerializer.cs / 1 / ComponentCodeDomSerializer.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ namespace System.ComponentModel.Design.Serialization { using System; using System.Design; using System.CodeDom; using System.Configuration; using System.Collections; using System.ComponentModel; using System.ComponentModel.Design; using System.Diagnostics; using System.Reflection; using System.Text; internal class ComponentCodeDomSerializer : CodeDomSerializer { private static readonly Type[] _containerConstructor = new Type[] {typeof(IContainer)}; private static readonly Attribute[] _runTimeFilter = new Attribute[] { DesignOnlyAttribute.No }; private static readonly Attribute[] _designTimeFilter = new Attribute[] { DesignOnlyAttribute.Yes }; private static ComponentCodeDomSerializer _default; ////// /// Retrieves a default static instance of this serializer. /// internal new static ComponentCodeDomSerializer Default { get { if (_default == null) { _default = new ComponentCodeDomSerializer(); } return _default; } } ////// Determines if we can cache the results of serializing a component. /// private bool CanCacheComponent(IDesignerSerializationManager manager, object value, PropertyDescriptorCollection props) { IComponent comp = value as IComponent; if (comp != null) { if (comp.Site != null) { INestedSite nestedSite = comp.Site as INestedSite; if (nestedSite != null && !string.IsNullOrEmpty(nestedSite.FullName)) { return false; } } if (props == null) { props = TypeDescriptor.GetProperties(comp); } foreach (PropertyDescriptor property in props) { if (typeof(IComponent).IsAssignableFrom(property.PropertyType) && !property.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden)) { MemberCodeDomSerializer memberSerializer = (MemberCodeDomSerializer)manager.GetSerializer(property.GetType(), typeof(MemberCodeDomSerializer)); if (memberSerializer != null && memberSerializer.ShouldSerialize(manager, value, property)) return false; } } } return true; } ////// This method is invoked during deserialization to obtain an instance of an object. When this is called, an instance /// of the requested type should be returned. This implementation calls base and then tries to deserialize design /// time properties for the component. /// protected override object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer) { object instance = base.DeserializeInstance(manager, type, parameters, name, addToContainer); if (instance != null) { Trace("Deserializing design time properties for {0}", manager.GetName(instance)); DeserializePropertiesFromResources(manager, instance, _designTimeFilter); } return instance; } ////// /// Serializes the given object into a CodeDom object. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] public override object Serialize(IDesignerSerializationManager manager, object value) { CodeStatementCollection statements = null; PropertyDescriptorCollection props = TypeDescriptor.GetProperties(value); using (TraceScope("ComponentCodeDomSerializer::Serialize")) { if (manager == null || value == null) { throw new ArgumentNullException(manager == null ? "manager" : "value"); } if (IsSerialized(manager, value)) { Debug.Fail("Serialize is being called twice for the same component"); return GetExpression(manager, value); } // If the object is being inherited, we will will not emit a variable declaration. Also, we won't // do any serialization at all if the object is privately inherited. InheritanceLevel inheritanceLevel = InheritanceLevel.NotInherited; InheritanceAttribute inheritanceAttribute = (InheritanceAttribute)TypeDescriptor.GetAttributes(value)[typeof(InheritanceAttribute)]; if (inheritanceAttribute != null) { inheritanceLevel = inheritanceAttribute.InheritanceLevel; } // First, skip everything if we're privately inherited. We cannot write any code that would affect this // component. TraceIf(inheritanceLevel == InheritanceLevel.InheritedReadOnly, "Skipping read only inherited component"); if (inheritanceLevel != InheritanceLevel.InheritedReadOnly) { // Things we need to know: // // 1. What expression should we use for the left hand side // a) already given to us via GetExpression? // b) a local variable? // c) a member variable? // // 2. Should we generate an init expression for this // object? // a) Inherited or existing expression: no // b) otherwise, yes. statements = new CodeStatementCollection(); CodeTypeDeclaration typeDecl = manager.Context[typeof(CodeTypeDeclaration)] as CodeTypeDeclaration; RootContext rootCxt = manager.Context[typeof(RootContext)] as RootContext; CodeExpression assignLhs = null; CodeExpression assignRhs; // Defaults for components bool generateLocal = false; bool generateField = true; bool generateObject = true; bool isComplete = false; assignLhs = GetExpression(manager, value); if (assignLhs != null) { Trace("Existing expression for LHS of value"); generateLocal = false; generateField = false; generateObject = false; // VSWhidbey 312327: if we have an existing expression and this is not // a sited component, do not serialize it. We need this for Everett / 1.0 // backwards compat (even though it's wrong). IComponent comp = value as IComponent; if (comp != null && comp.Site == null) { // And, VSWhidbey 445114: Everett detected when we were in a serialize content // property and would still serialize it. This code reverses what the // outer if block does for this specific case. We also need this // for Everett / 1.0 backwards compat. ExpressionContext expCxt = manager.Context[typeof(ExpressionContext)] as ExpressionContext; if (expCxt == null || expCxt.PresetValue != value) { isComplete = true; } } } else { Trace("Creating LHS expression"); if (inheritanceLevel == InheritanceLevel.NotInherited) { // See if there is a "GenerateMember" property. If so, // we might want to generate a local variable. Otherwise, // we want to generate a field. PropertyDescriptor generateProp = props["GenerateMember"]; if (generateProp != null && generateProp.PropertyType == typeof(bool) && !(bool)generateProp.GetValue(value)) { Trace("Object GenerateMember property wants a local variable"); generateLocal = true; generateField = false; } } else { generateObject = false; } if (rootCxt == null) { generateLocal = true; generateField = false; } } // Push the component being serialized onto the stack. It may be handy to // be able to discover this. manager.Context.Push(value); manager.Context.Push(statements); try { string name = manager.GetName(value); Type type = TypeDescriptor.GetReflectionType(value); string typeName = TypeDescriptor.GetClassName(value); // Output variable / field declarations if we need to if ((generateField || generateLocal) && name != null) { if (generateField) { if (inheritanceLevel == InheritanceLevel.NotInherited) { // We need to generate the field declaration. See if there is a modifiers property on // the object. If not, look for a DefaultModifies, and finally assume it's private. CodeMemberField field = new CodeMemberField(typeName, name); PropertyDescriptor modifersProp = props["Modifiers"]; MemberAttributes fieldAttrs; if (modifersProp == null) { modifersProp = props["DefaultModifiers"]; } if (modifersProp != null && modifersProp.PropertyType == typeof(MemberAttributes)) { fieldAttrs = (MemberAttributes)modifersProp.GetValue(value); } else { TraceWarning("No Modifiers or DefaultModifiers property on component {0}. We must assume private.", name); fieldAttrs = MemberAttributes.Private; } field.Attributes = fieldAttrs; typeDecl.Members.Add(field); Trace("Field {0} {1} {2} created.", fieldAttrs, typeName, name); } // Next, create a nice LHS for our pending assign statement, when we hook up the variable. assignLhs = new CodeFieldReferenceExpression(rootCxt.Expression, name); } else { if (inheritanceLevel == InheritanceLevel.NotInherited) { CodeVariableDeclarationStatement local = new CodeVariableDeclarationStatement(typeName, name); statements.Add(local); Trace("Local {0} {1} created.", typeName, name); } assignLhs = new CodeVariableReferenceExpression(name); } } // Now output an object create if we need to. We always see if there is a // type converter that can provide us guidance if (generateObject) { // Ok, now that we've decided if we have a local or a member variable, its now time to serialize the rest of the code. // The first step is to create an assign statement to "new" the object. For that, we need to know if // the component wants a special IContainer constructor or not. For that to be valid we must also know // that we can get to an actual IContainer. IContainer container = manager.GetService(typeof(IContainer)) as IContainer; ConstructorInfo ctor = TypeDescriptor.GetReflectionType(value).GetConstructor(BindingFlags.ExactBinding | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, _containerConstructor, null); if (ctor != null && container != null) { Trace("Component has IContainer constructor."); assignRhs = new CodeObjectCreateExpression(typeName, new CodeExpression[] { SerializeToExpression(manager, container) }); } else { // For compat reasons we ignore the isCompleteOld value here. // See VSWhidbey 415411 for more information. bool isCompleteOld; assignRhs = SerializeCreationExpression(manager, value, out isCompleteOld); Debug.Assert(isCompleteOld == isComplete, "CCDS Differing"); } TraceErrorIf(assignRhs == null, "No RHS code assign for object {0}", value); if (assignRhs != null) { if (assignLhs == null) { // We cannot do much more for this object. If isComplete is true, // then the RHS now becomes our LHS. Otherwise, I'm afraid we have // just failed to serialize this object. if (isComplete) { assignLhs = assignRhs; } else { TraceError("Incomplete serialization of object, abandoning serialization."); } } else { CodeAssignStatement assign = new CodeAssignStatement(assignLhs, assignRhs); statements.Add(assign); } } } if (assignLhs != null) { SetExpression(manager, value, assignLhs); } // It should practically be an assert that isComplete is false, but someone may // have a really funky component. if (assignLhs != null && !isComplete) { // VSWhidbey #111957 -.NET CF needs us to verify that the ISupportInitialize interface exists // (they do not support this interface and will modify their DSM to resolve the type to null). bool supportInitialize = (value is ISupportInitialize) && manager.GetType(typeof(ISupportInitialize).FullName) != null; bool persistSettings = (value is IPersistComponentSettings) && ((IPersistComponentSettings)value).SaveSettings && manager.GetType(typeof(IPersistComponentSettings).FullName) != null; // We implement statement caching only for the main code generation phase. We don't implement it for other // serialization managers. How do we tell the difference? The main serialization manager exists as a service. IDesignerSerializationManager mainManager = (IDesignerSerializationManager)manager.GetService(typeof(IDesignerSerializationManager)); if (supportInitialize) { Trace("Object implements ISupportInitialize."); SerializeSupportInitialize(manager, statements, assignLhs, value, "BeginInit"); } SerializePropertiesToResources(manager, statements, value, _designTimeFilter); // Writing out properties is expensive. But, we're very smart and we cache the results // in ComponentCache. See if we have cached results. If so, use 'em. If not, generate // code and then see if we can cache the results for later. ComponentCache cache = (ComponentCache)manager.GetService(typeof(ComponentCache)); ComponentCache.Entry entry = null; if (cache == null) { IServiceContainer sc = (IServiceContainer)manager.GetService(typeof(IServiceContainer)); if (sc != null) { cache = new ComponentCache(manager); sc.AddService(typeof(ComponentCache), cache); } } else { if (manager == mainManager && cache != null && cache.Enabled) { entry = cache[value]; } } if (entry == null || entry.Tracking) { // Pushing the entry here allows it to be found by the resource code dom serializer, // which will add data to the ResourceBlob property on the entry. if (entry == null) { entry = new ComponentCache.Entry(cache); // VSWhidbey 410415 // We cache components even if they're not valid so dependencies are // still tracked correctly (see comment below). The problem is, we will create a // new entry object even if there is still an existing one that is just invalid, and it // might have depenendecies that will be lost. // we need to make sure we copy oevr any dependencies that are also tracked. ComponentCache.Entry oldEntry = null; oldEntry = cache.GetEntryAll(value); if (oldEntry != null && oldEntry.Dependencies != null && oldEntry.Dependencies.Count > 0) { foreach(object dependency in oldEntry.Dependencies) { entry.AddDependency(dependency); } } } entry.Component = value; // we need to link the cached entry with its corresponding component right away, before it's put in the context // see CodeDomSerializerBase.cs::GetExpression for usage // This entry will only be used if the valid bit is set. // This is useful because we still need to setup depedency relationships // between components even if they are not cached. See VSWhidbey 263053. bool correctManager = manager == mainManager; entry.Valid = correctManager && CanCacheComponent(manager, value, props); if (correctManager && cache != null && cache.Enabled) { manager.Context.Push(cache); manager.Context.Push(entry); } try { entry.Statements = new CodeStatementCollection(); SerializeProperties(manager, entry.Statements, value, _runTimeFilter); SerializeEvents(manager, entry.Statements, value, null); foreach (CodeStatement statement in entry.Statements) { CodeVariableDeclarationStatement local = statement as CodeVariableDeclarationStatement; if (local != null) { entry.Tracking = true; break; } } if (entry.Statements.Count > 0) { // if we added some statements, insert the comments // entry.Statements.Insert(0, new CodeCommentStatement(string.Empty)); entry.Statements.Insert(0, new CodeCommentStatement(name)); entry.Statements.Insert(0, new CodeCommentStatement(string.Empty)); // // cache the statements for future usage if possible. We only do this for the main serialization manager, not // for any other seriallization managers that may be calling us for undo or clipboard functions. if (correctManager && cache != null && cache.Enabled) { cache[value] = entry; } } } finally { if (correctManager && cache != null && cache.Enabled) { Debug.Assert(manager.Context.Current == entry, "Context stack corrupted"); manager.Context.Pop(); manager.Context.Pop(); } } } else { // If we got a cache entry, we will need to take all the resources out of // it and apply them too. if ((entry.Resources != null || entry.Metadata != null) && cache != null && cache.Enabled) { ResourceCodeDomSerializer res = ResourceCodeDomSerializer.Default; res.ApplyCacheEntry(manager, entry); } } // Regarless, apply statements. Either we created them or we got them // out of the cache. statements.AddRange(entry.Statements); if (persistSettings) { SerializeLoadComponentSettings(manager, statements, assignLhs, value); } if (supportInitialize) { SerializeSupportInitialize(manager, statements, assignLhs, value, "EndInit"); } } } catch (CheckoutException) { throw; } catch (Exception ex) { manager.ReportError(ex); } finally { Debug.Assert(manager.Context.Current == statements, "Context stack corrupted"); manager.Context.Pop(); manager.Context.Pop(); } } } return statements; } ////// /// This emits a method invoke to IPersistComponentSettings.LoadComponentSettings. /// private void SerializeLoadComponentSettings(IDesignerSerializationManager manager, CodeStatementCollection statements, CodeExpression valueExpression, object value) { Trace("Emitting LoadComponentSettings"); CodeTypeReference type = new CodeTypeReference(typeof(IPersistComponentSettings)); CodeCastExpression castExp = new CodeCastExpression(type, valueExpression); CodeMethodReferenceExpression method = new CodeMethodReferenceExpression(castExp, "LoadComponentSettings"); CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(); methodInvoke.Method = method; CodeExpressionStatement statement = new CodeExpressionStatement(methodInvoke); statement.UserData["statement-ordering"] = "end"; statements.Add(statement); } ////// /// This emits a method invoke to ISupportInitialize. /// private void SerializeSupportInitialize(IDesignerSerializationManager manager, CodeStatementCollection statements, CodeExpression valueExpression, object value, string methodName) { Trace("Emitting {0}", methodName); CodeTypeReference type = new CodeTypeReference(typeof(ISupportInitialize)); CodeCastExpression castExp = new CodeCastExpression(type, valueExpression); CodeMethodReferenceExpression method = new CodeMethodReferenceExpression(castExp, methodName); CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(); methodInvoke.Method = method; CodeExpressionStatement statement = new CodeExpressionStatement(methodInvoke); if (methodName == "BeginInit") { statement.UserData["statement-ordering"] = "begin"; } else { statement.UserData["statement-ordering"] = "end"; } statements.Add(statement); } } } // 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
- TextBoxBase.cs
- StrokeFIndices.cs
- AnnotationHelper.cs
- WsatProxy.cs
- UntypedNullExpression.cs
- WebBrowserPermission.cs
- CqlWriter.cs
- CallTemplateAction.cs
- DoubleStorage.cs
- RefreshPropertiesAttribute.cs
- WorkerRequest.cs
- ResolveNextArgumentWorkItem.cs
- Byte.cs
- ResourceSetExpression.cs
- _SslState.cs
- Attributes.cs
- FormViewUpdatedEventArgs.cs
- TextEncodedRawTextWriter.cs
- KeyboardNavigation.cs
- FunctionImportMapping.cs
- BCryptSafeHandles.cs
- EncoderBestFitFallback.cs
- ObjectComplexPropertyMapping.cs
- parserscommon.cs
- DetailsViewDeletedEventArgs.cs
- WindowsFormsHelpers.cs
- SchemaNotation.cs
- UTF32Encoding.cs
- Vector3DKeyFrameCollection.cs
- Pair.cs
- DataServiceRequest.cs
- DefaultAuthorizationContext.cs
- CurrencyWrapper.cs
- CodeGenerator.cs
- Vector3DConverter.cs
- DecoderExceptionFallback.cs
- WebPartEditVerb.cs
- RichTextBoxAutomationPeer.cs
- Exception.cs
- MetadataPropertyvalue.cs
- OdbcConnection.cs
- DeviceContexts.cs
- CaseStatementSlot.cs
- PrefixQName.cs
- CollaborationHelperFunctions.cs
- SmiRecordBuffer.cs
- ApplicationFileCodeDomTreeGenerator.cs
- RegexCapture.cs
- input.cs
- CheckBox.cs
- SpecularMaterial.cs
- TraceHandlerErrorFormatter.cs
- ParentQuery.cs
- Vector3DCollectionValueSerializer.cs
- DrawingState.cs
- StringResourceManager.cs
- SmtpNetworkElement.cs
- PropertySet.cs
- TextServicesDisplayAttributePropertyRanges.cs
- Activity.cs
- WriteLine.cs
- Encoding.cs
- DataBoundControlDesigner.cs
- AttributeEmitter.cs
- Logging.cs
- SubordinateTransaction.cs
- PerspectiveCamera.cs
- TransformGroup.cs
- Size.cs
- ConfigUtil.cs
- Buffer.cs
- ColumnClickEvent.cs
- WindowsAuthenticationEventArgs.cs
- XmlBinaryReader.cs
- SoapElementAttribute.cs
- HandoffBehavior.cs
- ScriptServiceAttribute.cs
- GridProviderWrapper.cs
- X509CertificateCollection.cs
- GPPOINTF.cs
- RightsManagementEncryptionTransform.cs
- ListViewInsertedEventArgs.cs
- DynamicFilter.cs
- ObfuscateAssemblyAttribute.cs
- PolygonHotSpot.cs
- SoapAttributes.cs
- SelectionProcessor.cs
- ToolTipAutomationPeer.cs
- XmlSchemaRedefine.cs
- Empty.cs
- Scripts.cs
- XsdBuilder.cs
- ValidatorCollection.cs
- OleDbConnectionInternal.cs
- WebException.cs
- SystemFonts.cs
- ExpressionVisitor.cs
- MonthChangedEventArgs.cs
- GraphicsPathIterator.cs
- ZipIOLocalFileBlock.cs