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
- DocumentViewerAutomationPeer.cs
- MachineKeySection.cs
- MimeTypeMapper.cs
- DependencyProperty.cs
- ModuleElement.cs
- ToolboxItem.cs
- PropertyKey.cs
- LayoutSettings.cs
- ToolStripItemRenderEventArgs.cs
- GridViewRowPresenter.cs
- ListViewSelectEventArgs.cs
- QueuedDeliveryRequirementsMode.cs
- MouseActionValueSerializer.cs
- UInt16.cs
- HtmlElement.cs
- CodeRegionDirective.cs
- GridSplitterAutomationPeer.cs
- OperatingSystem.cs
- DateTimeValueSerializerContext.cs
- OdbcFactory.cs
- StringWriter.cs
- ReflectionHelper.cs
- TextElementEditingBehaviorAttribute.cs
- FrameworkElement.cs
- XmlSchemaValidator.cs
- ObjectParameter.cs
- DynamicRenderer.cs
- SoapAttributes.cs
- SafeNativeMethods.cs
- embossbitmapeffect.cs
- ParsedAttributeCollection.cs
- SessionStateSection.cs
- TextSpan.cs
- newinstructionaction.cs
- EmbeddedObject.cs
- Queue.cs
- IteratorFilter.cs
- TextElement.cs
- PingOptions.cs
- BatchStream.cs
- KnownIds.cs
- StringExpressionSet.cs
- ControllableStoryboardAction.cs
- SmtpSection.cs
- FormattedText.cs
- StateMachineWorkflowInstance.cs
- SafeCertificateStore.cs
- ToolboxCategory.cs
- safelink.cs
- Variable.cs
- ToolStripContentPanelDesigner.cs
- UITypeEditor.cs
- IndentTextWriter.cs
- DbSetClause.cs
- PassportAuthenticationEventArgs.cs
- UniqueCodeIdentifierScope.cs
- OletxEnlistment.cs
- RightsManagementPermission.cs
- ObjectIDGenerator.cs
- CompilerScope.cs
- SelectionService.cs
- MenuItemBinding.cs
- ConditionalBranch.cs
- TemplateBamlRecordReader.cs
- ContractTypeNameElement.cs
- querybuilder.cs
- SpellCheck.cs
- DSASignatureFormatter.cs
- RSAOAEPKeyExchangeDeformatter.cs
- Matrix3D.cs
- RadioButtonBaseAdapter.cs
- HttpListenerRequest.cs
- DbConnectionOptions.cs
- ListenerChannelContext.cs
- AtomServiceDocumentSerializer.cs
- RowParagraph.cs
- VideoDrawing.cs
- AnimationClock.cs
- MetadataElement.cs
- DataTableTypeConverter.cs
- EpmAttributeNameBuilder.cs
- CodeTypeDeclaration.cs
- Soap11ServerProtocol.cs
- MailHeaderInfo.cs
- EmptyStringExpandableObjectConverter.cs
- TerminatorSinks.cs
- WindowsScrollBarBits.cs
- OdbcUtils.cs
- DependencyProperty.cs
- NotifyCollectionChangedEventArgs.cs
- HttpCapabilitiesSectionHandler.cs
- OdbcConnectionFactory.cs
- SiteMapSection.cs
- Authorization.cs
- ChildrenQuery.cs
- SourceItem.cs
- AvTraceDetails.cs
- WebScriptMetadataMessage.cs
- StyleCollection.cs
- ZipIOBlockManager.cs