diff --git a/src/System.Windows.Forms.Design/src/Resources/SR.resx b/src/System.Windows.Forms.Design/src/Resources/SR.resx
index fbc9af7eb4a..c76994d4e97 100644
--- a/src/System.Windows.Forms.Design/src/Resources/SR.resx
+++ b/src/System.Windows.Forms.Design/src/Resources/SR.resx
@@ -300,4 +300,79 @@
The extender provider {0} has already been added as an extender. Adding another would result in duplicate properties.
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+ The type '{0}' has no event named '{1}'.
+
+
+ The type '{0}' has no field named '{1}'.
+
+
+ The type '{0}' has no property named '{1}'.
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+ Error reading resources from the resource file for the default culture: {0}
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+
+
+ Type '{0}' is not available in the target framework.
+
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+ Duplicate declaration of member '{0}'
+
+
+ The name '{0}' is already used by another object.
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+ Members of type '{0}' cannot be serialized.
+
+
+ Complete deserialization of {0} failed.
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.cs.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.cs.xlf
index 65e08772c19..c333765cdd4 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.cs.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.cs.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Winforms Designer není na této platformě podporován.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.de.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.de.xlf
index 3779dd82122..ad321646c69 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.de.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.de.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Der Windows Forms-Designer wird auf dieser Plattform nicht unterstützt.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.es.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.es.xlf
index 758f40b5e8a..d7137ea32a1 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.es.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.es.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Winforms Designer no se admite en esta plataforma.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.fr.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.fr.xlf
index 4c091290204..04cd8b71975 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.fr.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.fr.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Le concepteur WinForms n'est pas pris en charge sur cette plateforme.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.it.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.it.xlf
index 504c2584a00..4f255d476df 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.it.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.it.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Winforms Designer non è supportato in questa piattaforma.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ja.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ja.xlf
index 0a166a47a0d..ccd31968af1 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ja.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ja.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Windows フォーム デザイナーは、このプラットフォームではサポートされていません。
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ko.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ko.xlf
index 98e5ce56228..1e06f8b478e 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ko.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ko.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Winforms 디자이너는 이 플랫폼에서 지원되지 않습니다.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pl.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pl.xlf
index 74b8203c25a..8e04aa4658b 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pl.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pl.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Projektant formularzy systemu Windows nie jest obsługiwany na tej platformie.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pt-BR.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pt-BR.xlf
index cbc189755d4..dc29c6a82d2 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pt-BR.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.pt-BR.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
O Designer de Formulários do Windows não é compatível com esta plataforma.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ru.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ru.xlf
index d6e64a3661e..b8a6f7ac3fc 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ru.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.ru.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Конструктор Windows Forms не поддерживается на этой платформе.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.tr.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.tr.xlf
index de04a73d57f..cb19f5787c8 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.tr.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.tr.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
Winforms Tasarımcısı bu platformda desteklenmiyor.
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hans.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hans.xlf
index 36f29a58346..a86e3506982 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hans.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hans.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
此平台上不支持 Winforms Designer。
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hant.xlf b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hant.xlf
index c508c6c12d3..21a336230b0 100644
--- a/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hant.xlf
+++ b/src/System.Windows.Forms.Design/src/Resources/xlf/SR.zh-Hant.xlf
@@ -2,6 +2,21 @@
+
+ The serialization store is closed. New objects cannot be added to a closed store.
+ The serialization store is closed. New objects cannot be added to a closed store.
+
+
+
+ Complete deserialization of {0} failed.
+ Complete deserialization of {0} failed.
+
+
+
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+ This type of serialization store is not supported. Use a store returned by the CreateStore method.
+
+ Adding event '{0}'Adding event '{0}'
@@ -237,6 +252,111 @@
此平台不支援 WinForms Designer。
+
+ You cannot create a new session because this serialization manager already has an active serialization session.
+ You cannot create a new session because this serialization manager already has an active serialization session.
+
+
+
+ Duplicate declaration of member '{0}'
+ Duplicate declaration of member '{0}'
+
+
+
+ The name '{0}' is already used by another object.
+ The name '{0}' is already used by another object.
+
+
+
+ Type '{0}' does not have a constructor with parameters of types {1}.
+ Type '{0}' does not have a constructor with parameters of types {1}.
+
+
+
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+ This method cannot be invoked because the serialization manager does not have an active serialization session.
+
+
+
+ Cannot name the object '{0}' because it is already named '{1}'.
+ Cannot name the object '{0}' because it is already named '{1}'.
+
+
+
+ This method cannot be invoked because the serialization manager has an active serialization session.
+ This method cannot be invoked because the serialization manager has an active serialization session.
+
+
+
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+ Elements of type {0} are not supported. The serializer expects the element to be one of the following: {1}.
+
+
+
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+ The field '{0}' could not be found on the target object. Make sure that the field is defined as an instance variable on the target object and has the correct scope.
+
+
+
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+ Array rank '{0}' is too high. Visual Studio can only save and load arrays with a rank of 1.
+
+
+
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+ Code statements for the object '{0}' were lost during serialization. This may have been a result of another object misbehaving during serialization.
+
+
+
+ Members of type '{0}' cannot be serialized.
+ Members of type '{0}' cannot be serialized.
+
+
+
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+ The source code contains a reference to the class definition, but the class definition cannot be found.
+
+
+
+ The object '{0}' failed to serialize itself. It may not support code generation.
+ The object '{0}' failed to serialize itself. It may not support code generation.
+
+
+
+ The type '{0}' has no event named '{1}'.
+ The type '{0}' has no event named '{1}'.
+
+
+
+ The type '{0}' has no field named '{1}'.
+ The type '{0}' has no field named '{1}'.
+
+
+
+ The type '{0}' has no property named '{1}'.
+ The type '{0}' has no property named '{1}'.
+
+
+
+ Error reading resources from the resource file for the culture {0}: {1}
+ Error reading resources from the resource file for the culture {0}: {1}
+
+
+
+ Error reading resources from the resource file for the default culture: {0}
+ Error reading resources from the resource file for the default culture: {0}
+
+
+
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+ Could not find type '{0}'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU.
+
+
+
+ The variable '{0}' is either undeclared or was never assigned.
+ The variable '{0}' is either undeclared or was never assigned.
+
+ Argument should be a non-empty string.Argument should be a non-empty string.
@@ -257,6 +377,11 @@
Data type {0} is not serializable. Items added to a property dictionary must be serializable.
+
+ Type '{0}' is not available in the target framework.
+ Type '{0}' is not available in the target framework.
+
+ Add ComponentAdd Component
diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionItem.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionItem.cs
index 173cea29978..545959df806 100644
--- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionItem.cs
+++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerActionItem.cs
@@ -26,7 +26,7 @@ public DesignerActionItem(string displayName, string category, string descriptio
{
_category = category;
_description = description;
- _displayName = displayName == null ? null : Regex.Replace(displayName, @"\(\&.\)", ""); // VSWHIDBEY 485835
+ _displayName = displayName == null ? null : Regex.Replace(displayName, @"\(\&.\)", "");
}
internal DesignerActionItem()
diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerHost.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerHost.cs
index 97f44f70476..aa4897ea3f0 100644
--- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerHost.cs
+++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/DesignerHost.cs
@@ -1115,7 +1115,7 @@ IComponent IDesignerHost.CreateComponent(Type componentType, string name)
IComponent component;
LicenseContext oldContext = LicenseManager.CurrentContext;
- bool changingContext = false; // we don't want if there is a recursivity (creating a component create another one) to change the context again. we already have the one we want and that would create a locking problem. see bug VSWhidbey 441200
+ bool changingContext = false; // we don't want if there is a recursivity (creating a component create another one) to change the context again. we already have the one we want and that would create a locking problem.
if (oldContext != LicenseContext)
{
LicenseManager.CurrentContext = LicenseContext;
diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomComponentSerializationService.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomComponentSerializationService.cs
new file mode 100644
index 00000000000..1868686e466
--- /dev/null
+++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomComponentSerializationService.cs
@@ -0,0 +1,1665 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.CodeDom;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+
+namespace System.ComponentModel.Design.Serialization
+{
+ ///
+ /// This class serializes a set of components or serializable objects into a serialization store. The store can then be deserialized at a later date. CodeDomComponentSerializationService differs from other serialization schemes in that the serialization format is opaque, and it allows for partial serialization of objects. For example, you can choose to serialize only selected properties for an object.
+ ///
+ public sealed class CodeDomComponentSerializationService : ComponentSerializationService
+ {
+ private readonly IServiceProvider _provider;
+
+ ///
+ /// Creates a new CodeDomComponentSerializationService object.
+ ///
+ public CodeDomComponentSerializationService() : this(null)
+ {
+ }
+
+ ///
+ /// Creates a new CodeDomComponentSerializationService object using the given service provider to resolve services.
+ ///
+ public CodeDomComponentSerializationService(IServiceProvider provider)
+ {
+ _provider = provider;
+ }
+
+ ///
+ /// This method creates a new SerializationStore. The serialization store can be passed to any of the various Serialize methods to build up serialization state for a group of objects.
+ ///
+ public override SerializationStore CreateStore()
+ {
+ return new CodeDomSerializationStore(_provider);
+ }
+
+ ///
+ /// This method loads a SerializationStore and from the given stream. This store can then be used to deserialize objects by passing it to the various Deserialize methods.
+ ///
+ public override SerializationStore LoadStore(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException(nameof(stream));
+ return CodeDomSerializationStore.Load(stream);
+ }
+
+ ///
+ /// This method serializes the given object to the store. The store can be used to serialize more than one object by calling this method more than once.
+ ///
+ public override void Serialize(SerializationStore store, object value)
+ {
+ if (store == null) throw new ArgumentNullException(nameof(store));
+ if (value == null) throw new ArgumentNullException(nameof(value));
+ if (!(store is CodeDomSerializationStore cdStore)) throw new InvalidOperationException(SR.CodeDomComponentSerializationServiceUnknownStore);
+ cdStore.AddObject(value, false);
+ }
+
+ ///
+ /// This method serializes the given object to the store. The store can be used to serialize more than one object by calling this method more than once.
+ ///
+ public override void SerializeAbsolute(SerializationStore store, object value)
+ {
+ if (store == null) throw new ArgumentNullException(nameof(store));
+ if (value == null) throw new ArgumentNullException(nameof(value));
+ if (!(store is CodeDomSerializationStore cdStore)) throw new InvalidOperationException(SR.CodeDomComponentSerializationServiceUnknownStore);
+ cdStore.AddObject(value, true);
+ }
+
+ ///
+ /// This method serializes the given member on the given object. This method can be invoked multiple times for the same object to build up a list of serialized members within the serialization store. The member generally has to be a property or an event.
+ ///
+ public override void SerializeMember(SerializationStore store, object owningObject, MemberDescriptor member)
+ {
+ if (store == null) throw new ArgumentNullException(nameof(store));
+ if (owningObject == null) throw new ArgumentNullException(nameof(owningObject));
+ if (member == null) throw new ArgumentNullException(nameof(member));
+ if (!(store is CodeDomSerializationStore cdStore)) throw new InvalidOperationException(SR.CodeDomComponentSerializationServiceUnknownStore);
+ cdStore.AddMember(owningObject, member, false);
+ }
+
+ ///
+ /// This method serializes the given member on the given object, but also serializes the member if it contains the default value.
+ /// Note that for some members, containing the default value and setting the same value back to the member are different concepts. For example, if a property inherits its value from a parent object if no local value is set, setting the value back to the property can may not be what is desired. SerializeMemberAbsolute takes this into account and would clear the state of the property in this case.
+ ///
+ public override void SerializeMemberAbsolute(SerializationStore store, object owningObject, MemberDescriptor member)
+ {
+ if (store == null) throw new ArgumentNullException(nameof(store));
+ if (owningObject == null) throw new ArgumentNullException(nameof(owningObject));
+ if (member == null) throw new ArgumentNullException(nameof(member));
+ if (!(store is CodeDomSerializationStore cdStore)) throw new InvalidOperationException(SR.CodeDomComponentSerializationServiceUnknownStore);
+ cdStore.AddMember(owningObject, member, true);
+ }
+
+ ///
+ /// This method deserializes the given store to produce a collection of objects contained within it. If a container is provided, objects that are created that implement IComponent will be added to the container.
+ ///
+ public override ICollection Deserialize(SerializationStore store)
+ {
+ if (store == null) throw new ArgumentNullException(nameof(store));
+ if (!(store is CodeDomSerializationStore cdStore)) throw new InvalidOperationException(SR.CodeDomComponentSerializationServiceUnknownStore);
+ return cdStore.Deserialize(_provider);
+ }
+
+ ///
+ /// This method deserializes the given store to produce a collection of objects contained within it. If a container is provided, objects that are created that implement IComponent will be added to the container.
+ ///
+ public override ICollection Deserialize(SerializationStore store, IContainer container)
+ {
+ if (store == null) throw new ArgumentNullException(nameof(store));
+ if (container == null) throw new ArgumentNullException(nameof(container));
+ if (!(store is CodeDomSerializationStore cdStore)) throw new InvalidOperationException(SR.CodeDomComponentSerializationServiceUnknownStore);
+ return cdStore.Deserialize(_provider, container);
+ }
+
+ ///
+ /// This method deserializes the given store, but rather than produce new objects object, the data in the store is applied to an existing set of objects that are taken from the provided container. This allows the caller to pre-create an object however it sees fit. If an object has deserialization state and the object is not named in the set of existing objects, a new object will be created. If that object also implements IComponent, it will be added to the given container. Objects in the container must have names and types that match objects in the serialization store in order for an existing object to be used.
+ ///
+ public override void DeserializeTo(SerializationStore store, IContainer container, bool validateRecycledTypes, bool applyDefaults)
+ {
+ if (store == null) throw new ArgumentNullException(nameof(store));
+ if (container == null) throw new ArgumentNullException(nameof(container));
+ if (!(store is CodeDomSerializationStore cdStore)) throw new InvalidOperationException(SR.CodeDomComponentSerializationServiceUnknownStore);
+ cdStore.DeserializeTo(_provider, container, validateRecycledTypes, applyDefaults);
+ }
+
+ ///
+ /// The SerializationStore class is an implementation-specific class that stores serialization data for the component serialization service. The service adds state to this serialization store. Once the store is closed it can be saved to a stream. A serialization store can be deserialized at a later date by the same type of serialization service. SerializationStore implements the IDisposable interface such that Dispose simply calls the Close method. Dispose is implemented as a private interface to avoid confusion. The IDisposable pattern is provided for languages that support a "using" syntax like C# and VB .NET.
+ ///
+ [Serializable]
+ private sealed class CodeDomSerializationStore : SerializationStore, ISerializable
+ {
+#if DEBUG
+ private static readonly TraceSwitch s_trace = new TraceSwitch("ComponentSerializationService", "Trace component serialization");
+#endif
+ private const string StateKey = "State";
+ private const string NameKey = "Names";
+ private const string AssembliesKey = "Assemblies";
+ private const string ResourcesKey = "Resources";
+ private const string ShimKey = "Shim";
+ private const int StateCode = 0;
+ private const int StateCtx = 1;
+ private const int StateProperties = 2;
+ private const int StateResources = 3;
+ private const int StateEvents = 4;
+ private const int StateModifier = 5;
+
+ private MemoryStream _resourceStream = null;
+
+ // Transient fields only used during creation of the store
+ private Hashtable _objects;
+ private readonly IServiceProvider _provider;
+
+ // These fields persist across the store
+ private readonly ArrayList _objectNames;
+ private Hashtable _objectState;
+ private LocalResourceManager _resources;
+ private AssemblyName[] _assemblies;
+ private readonly List _shimObjectNames;
+
+ // These fields are available after serialization or deserialization
+ private ICollection _errors;
+
+ ///
+ /// Creates a new store.
+ ///
+ internal CodeDomSerializationStore(IServiceProvider provider)
+ {
+ _provider = provider;
+ _objects = new Hashtable();
+ _objectNames = new ArrayList();
+ _shimObjectNames = new List();
+ }
+
+ ///
+ /// Used to deserialize ourselves from binary serialization.
+ ///
+ private CodeDomSerializationStore(SerializationInfo info, StreamingContext context)
+ {
+ _objectState = (Hashtable)info.GetValue(StateKey, typeof(Hashtable));
+ _objectNames = (ArrayList)info.GetValue(NameKey, typeof(ArrayList));
+ _assemblies = (AssemblyName[])info.GetValue(AssembliesKey, typeof(AssemblyName[]));
+ _shimObjectNames = (List)info.GetValue(ShimKey, typeof(List));
+ Hashtable h = (Hashtable)info.GetValue(ResourcesKey, typeof(Hashtable));
+
+ if (h != null)
+ {
+ _resources = new LocalResourceManager(h);
+ }
+ }
+
+ ///
+ /// Nested classes within us access this property to get to our array of saved assembly names.
+ ///
+ private AssemblyName[] AssemblyNames
+ {
+ get => _assemblies;
+ }
+
+ ///
+ /// If there were errors generated during serialization or deserialization of the store, they will be added to this collection.
+ ///
+ public override ICollection Errors
+ {
+ get
+ {
+ if (_errors == null)
+ {
+ _errors = new object[0];
+ }
+
+ object[] errors = new object[_errors.Count];
+ _errors.CopyTo(errors, 0);
+ return errors;
+ }
+ }
+
+ ///
+ /// Nested classes within us access this property to get to our collection of resources.
+ ///
+ private LocalResourceManager Resources
+ {
+ get
+ {
+ if (_resources == null)
+ {
+ _resources = new LocalResourceManager();
+ }
+ return _resources;
+ }
+ }
+
+ ///
+ /// Adds a new member serialization to our list of things to serialize.
+ ///
+ internal void AddMember(object value, MemberDescriptor member, bool absolute)
+ {
+ if (_objectState != null) throw new InvalidOperationException(SR.CodeDomComponentSerializationServiceClosedStore);
+ ObjectData data = (ObjectData)_objects[value];
+ if (data == null)
+ {
+ data = new ObjectData();
+ data._name = GetObjectName(value);
+ data._value = value;
+
+ _objects[value] = data;
+ _objectNames.Add(data._name);
+ }
+
+ Trace("Adding object '{0}' ({1}:{2}) {3}", data._name, data._value.GetType().FullName, member.Name, (absolute ? "NORMAL" : "ABSOLUTE"));
+ data.Members.Add(new MemberData(member, absolute));
+ }
+
+ ///
+ /// Adds a new object serialization to our list of things to serialize.
+ ///
+ internal void AddObject(object value, bool absolute)
+ {
+ if (_objectState != null)
+ throw new InvalidOperationException(SR.CodeDomComponentSerializationServiceClosedStore);
+ ObjectData data = (ObjectData)_objects[value];
+ if (data == null)
+ {
+ data = new ObjectData
+ {
+ _name = GetObjectName(value),
+ _value = value
+ };
+
+ _objects[value] = data;
+ _objectNames.Add(data._name);
+ }
+
+ Trace("Adding object '{0}' ({1}) {2}", data._name, data._value.GetType().FullName, (absolute ? "NORMAL" : "ABSOLUTE"));
+ data.EntireObject = true;
+ data.Absolute = absolute;
+ }
+
+ ///
+ /// The Close method closes this store and prevents any objects from being serialized into it. Once closed, the serialization store may be saved.
+ ///
+ public override void Close()
+ {
+ if (_objectState == null)
+ {
+ Hashtable state = new Hashtable(_objects.Count);
+ DesignerSerializationManager manager = new DesignerSerializationManager(new LocalServices(this, _provider));
+ if (_provider.GetService(typeof(IDesignerSerializationManager)) is DesignerSerializationManager hostManager)
+ {
+ foreach (IDesignerSerializationProvider provider in hostManager.SerializationProviders)
+ {
+ ((IDesignerSerializationManager)manager).AddSerializationProvider(provider);
+ }
+ }
+
+ Trace("Closing Store: serializing {0} objects", _objects.Count);
+ using (manager.CreateSession())
+ {
+ // Walk through our objects and name them so the serialization manager knows what names we gave them.
+ foreach (ObjectData data in _objects.Values)
+ {
+ ((IDesignerSerializationManager)manager).SetName(data._value, data._name);
+ }
+
+ ComponentListCodeDomSerializer.s_instance.Serialize(manager, _objects, state, _shimObjectNames);
+ _errors = manager.Errors;
+ }
+
+ // also serialize out resources if we have any we force this in order for undo to work correctly
+ if (_resources != null)
+ {
+ Debug.Assert(_resourceStream == null, "Attempting to close a serialization store with already serialized resources");
+ if (_resourceStream == null)
+ {
+ BinaryFormatter formatter = new BinaryFormatter();
+ _resourceStream = new MemoryStream();
+
+ formatter.Serialize(_resourceStream, _resources.Data);
+ }
+ }
+
+ Hashtable assemblies = new Hashtable(_objects.Count);
+ foreach (object obj in _objects.Keys)
+ {
+ // Save off the assembly for this object
+ Assembly a = obj.GetType().Assembly;
+ assemblies[a] = null;
+ }
+
+ _assemblies = new AssemblyName[assemblies.Count];
+ int idx = 0;
+
+ foreach (Assembly a in assemblies.Keys)
+ {
+ _assemblies[idx++] = a.GetName(true);
+ }
+#if DEBUG
+ foreach (DictionaryEntry de in state)
+ {
+ TraceCode((string)de.Key, de.Value);
+ }
+#endif
+ _objectState = state;
+ _objects = null;
+ }
+ }
+
+ ///
+ /// Deserializes the saved bits.
+ ///
+ internal ICollection Deserialize(IServiceProvider provider)
+ {
+ return Deserialize(provider, null, false, true, true);
+ }
+
+ ///
+ /// Deserializes the saved bits.
+ ///
+ internal ICollection Deserialize(IServiceProvider provider, IContainer container)
+ {
+ return Deserialize(provider, container, false, true, true);
+ }
+
+ private ICollection Deserialize(IServiceProvider provider, IContainer container, bool recycleInstances, bool validateRecycledTypes, bool applyDefaults)
+ {
+ PassThroughSerializationManager delegator = new PassThroughSerializationManager(new LocalDesignerSerializationManager(this, new LocalServices(this, provider)));
+ if (container != null)
+ {
+ delegator.Manager.Container = container;
+ }
+
+ if (provider.GetService(typeof(IDesignerSerializationManager)) is DesignerSerializationManager hostManager)
+ {
+ foreach (IDesignerSerializationProvider serProvider in hostManager.SerializationProviders)
+ {
+ ((IDesignerSerializationManager)delegator.Manager).AddSerializationProvider(serProvider);
+ }
+ }
+
+ // RecycleInstances is used so that we re-use objects already in the container. PreserveNames is used raise errors in the case of duplicate names. We only care about name preservation when we are recycling instances. Otherwise, we'd prefer to create objects with different names.
+ delegator.Manager.RecycleInstances = recycleInstances;
+ delegator.Manager.PreserveNames = recycleInstances;
+ delegator.Manager.ValidateRecycledTypes = validateRecycledTypes;
+ ArrayList objects = null;
+ // recreate resouces
+ if (_resourceStream != null)
+ {
+ BinaryFormatter formatter = new BinaryFormatter();
+ _resourceStream.Seek(0, SeekOrigin.Begin);
+ Hashtable resources = formatter.Deserialize(_resourceStream) as Hashtable;
+ _resources = new LocalResourceManager(resources);
+ }
+
+ if (!recycleInstances)
+ {
+ objects = new ArrayList(_objectNames.Count);
+ }
+
+ Trace("Deserializing {0} objects, recycling instances: {1}", _objectState.Count, recycleInstances);
+ using (delegator.Manager.CreateSession())
+ {
+ // before we deserialize, setup any references to components we faked during serialization
+ if (_shimObjectNames.Count > 0)
+ {
+ List names = _shimObjectNames;
+ if (delegator is IDesignerSerializationManager dsm && container != null)
+ {
+ foreach (string compName in names)
+ {
+ object instance = container.Components[compName];
+ if (instance != null && dsm.GetInstance(compName) == null)
+ {
+ dsm.SetName(instance, compName);
+ }
+ }
+ }
+ }
+
+ ComponentListCodeDomSerializer.s_instance.Deserialize(delegator, _objectState, _objectNames, applyDefaults);
+ if (!recycleInstances)
+ {
+ foreach (string name in _objectNames)
+ {
+ object instance = ((IDesignerSerializationManager)delegator.Manager).GetInstance(name);
+ Debug.Assert(instance != null, "Failed to deserialize object " + name);
+ if (instance != null)
+ {
+ objects.Add(instance);
+ }
+ }
+ }
+ _errors = delegator.Manager.Errors;
+ }
+ return objects;
+ }
+
+ ///
+ /// Deserializes the saved bits.
+ ///
+ internal void DeserializeTo(IServiceProvider provider, IContainer container, bool validateRecycledTypes, bool applyDefaults)
+ {
+ Deserialize(provider, container, true, validateRecycledTypes, applyDefaults);
+ }
+
+ ///
+ /// Gets a name for this object. It first tries the object's site, if it exists, and otherwise fabricates a unique name.
+ ///
+ private string GetObjectName(object value)
+ {
+ if (value is IComponent comp)
+ {
+ ISite site = comp.Site;
+ if (site != null)
+ {
+ if (site is INestedSite nestedSite && !string.IsNullOrEmpty(nestedSite.FullName))
+ {
+ return nestedSite.FullName;
+ }
+ else if (!string.IsNullOrEmpty(site.Name))
+ {
+ return site.Name;
+ }
+ }
+ }
+
+ Guid guid = Guid.NewGuid();
+ string guidStr = guid.ToString();
+ guidStr = guidStr.Replace("-", "_");
+ return string.Format(CultureInfo.CurrentCulture, "object_{0}", guidStr);
+ }
+
+ ///
+ /// Loads our state from a stream.
+ ///
+ internal static CodeDomSerializationStore Load(Stream stream)
+ {
+ BinaryFormatter f = new BinaryFormatter();
+ return (CodeDomSerializationStore)f.Deserialize(stream);
+ }
+
+ ///
+ /// The Save method saves the store to the given stream. If the store is open, Save will automatically close it for you. You can call save as many times as you wish to save the store to different streams.
+ ///
+ public override void Save(Stream stream)
+ {
+ Close();
+ BinaryFormatter f = new BinaryFormatter();
+ f.Serialize(stream, this);
+ }
+
+ [Conditional("DEBUG")]
+ internal static void Trace(string message, params object[] args)
+ {
+#if DEBUG
+ string msg = string.Format(CultureInfo.CurrentCulture, "ComponentSerialization: " + message, args);
+ Debug.WriteLineIf(s_trace.TraceVerbose, msg);
+#endif
+ }
+
+#if DEBUG
+ internal static void TraceCode(string name, object code)
+ {
+
+ if (code == null || !s_trace.TraceVerbose)
+ {
+ return;
+ }
+
+ // The code is stored as the first slot in an array.
+ object[] state = (object[])code;
+ code = state[StateCode];
+
+ if (code == null)
+ {
+ return;
+ }
+
+#pragma warning disable 618
+ System.CodeDom.Compiler.ICodeGenerator codeGenerator = new Microsoft.CSharp.CSharpCodeProvider().CreateGenerator();
+#pragma warning restore 618
+ StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
+ Trace("Stored CodeDom for {0}: ", name);
+ Debug.Indent();
+
+ if (code is CodeTypeDeclaration)
+ {
+ codeGenerator.GenerateCodeFromType((CodeTypeDeclaration)code, sw, null);
+ }
+ else if (code is CodeStatementCollection statements)
+ {
+ foreach (CodeStatement statement in statements)
+ {
+ codeGenerator.GenerateCodeFromStatement(statement, sw, null);
+ }
+ }
+ else if (code is CodeStatement)
+ {
+ codeGenerator.GenerateCodeFromStatement((CodeStatement)code, sw, null);
+ }
+ else if (code is CodeExpression)
+ {
+ codeGenerator.GenerateCodeFromExpression((CodeExpression)code, sw, null);
+ }
+ else
+ {
+ sw.Write("Unknown code type: " + code.GetType().Name);
+ sw.Write("\r\n");
+ }
+
+ // spit this line by line so it respects the indent.
+ StringReader sr = new StringReader(sw.ToString());
+ for (string ln = sr.ReadLine(); ln != null; ln = sr.ReadLine())
+ {
+ Debug.WriteLine(ln);
+ }
+ Debug.Unindent();
+ }
+#endif
+
+ ///
+ /// Implements the save part of ISerializable.
+ ///
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ Hashtable resources = null;
+ if (_resources != null)
+ {
+ resources = _resources.Data;
+ }
+
+ info.AddValue(StateKey, _objectState);
+ info.AddValue(NameKey, _objectNames);
+ info.AddValue(AssembliesKey, _assemblies);
+ info.AddValue(ResourcesKey, resources);
+ info.AddValue(ShimKey, _shimObjectNames);
+ }
+
+ ///
+ /// This is a simple code dom serializer that serializes a set of objects as a unit.
+ ///
+ private class ComponentListCodeDomSerializer : CodeDomSerializer
+ {
+ internal static ComponentListCodeDomSerializer s_instance = new ComponentListCodeDomSerializer();
+ private Hashtable _statementsTable;
+ Dictionary _expressions;
+ private Hashtable _objectState; // only used during deserialization
+ private bool _applyDefaults = true;
+ private readonly Hashtable _nameResolveGuard = new Hashtable();
+
+ public override object Deserialize(IDesignerSerializationManager manager, object state)
+ {
+ throw new NotSupportedException();
+ }
+
+ private void PopulateCompleteStatements(object data, string name, CodeStatementCollection completeStatements)
+ {
+ if (data is CodeStatementCollection statements)
+ {
+ completeStatements.AddRange(statements);
+ }
+ else if (data is CodeStatement statement)
+ {
+ completeStatements.Add(statement);
+ }
+ else if (data is CodeExpression expression)
+ {
+ // we handle expressions a little differently since they don't have a LHS or RHS they won't show up correctly in the statement table. We will deserialize them explicitly.
+ ArrayList exps = null;
+ if (_expressions.ContainsKey(name))
+ {
+ exps = _expressions[name];
+ }
+ if (exps == null)
+ {
+ exps = new ArrayList();
+ _expressions[name] = exps;
+ }
+ exps.Add(expression);
+ }
+ else
+ {
+ Debug.Fail("No case for " + data.GetType().Name);
+ }
+ }
+ ///
+ /// Deserializes the given object state. The results are contained within the serialization manager's name table. The objectNames list is used to deserialize in the proper order, as objectState is unordered.
+ ///
+ internal void Deserialize(IDesignerSerializationManager manager, IDictionary objectState, IList objectNames, bool applyDefaults)
+ {
+ CodeStatementCollection completeStatements = new CodeStatementCollection();
+ _expressions = new Dictionary();
+ _applyDefaults = applyDefaults;
+ foreach (string name in objectNames)
+ {
+ object[] state = (object[])objectState[name];
+ if (state != null)
+ {
+ if (state[StateCode] != null)
+ {
+ PopulateCompleteStatements(state[StateCode], name, completeStatements);
+ }
+ if (state[StateCtx] != null)
+ {
+ PopulateCompleteStatements(state[StateCtx], name, completeStatements);
+ }
+ }
+ }
+ CodeStatementCollection mappedStatements = new CodeStatementCollection();
+ CodeMethodMap methodMap = new CodeMethodMap(mappedStatements, null);
+
+ methodMap.Add(completeStatements);
+ methodMap.Combine();
+ _statementsTable = new Hashtable();
+
+ // generate statement table keyed on component name
+ CodeDomSerializerBase.FillStatementTable(manager, _statementsTable, mappedStatements);
+
+ // We need to also ensure that for every entry in the statement table we have a corresponding entry in objectNames. Otherwise, we won't deserialize completely.
+ ArrayList completeNames = new ArrayList(objectNames);
+ foreach (string mappedKey in _statementsTable.Keys)
+ {
+ if (!completeNames.Contains(mappedKey))
+ {
+ completeNames.Add(mappedKey);
+ }
+ }
+
+ _objectState = new Hashtable(objectState.Keys.Count);
+ foreach (DictionaryEntry de in objectState)
+ {
+ _objectState.Add(de.Key, de.Value);
+ }
+
+ ResolveNameEventHandler resolveNameHandler = new ResolveNameEventHandler(OnResolveName);
+ manager.ResolveName += resolveNameHandler;
+ try
+ {
+ foreach (string name in completeNames)
+ {
+ ResolveName(manager, name, true);
+ }
+ }
+ finally
+ {
+ _objectState = null;
+ manager.ResolveName -= resolveNameHandler;
+ }
+ }
+
+ private void OnResolveName(object sender, ResolveNameEventArgs e)
+ {
+ //note: this recursionguard does not fix the problem, but rathar avoids a stack overflow which will bring down VS and cause loss of data.
+ if (_nameResolveGuard.ContainsKey(e.Name))
+ {
+ return;
+ }
+ _nameResolveGuard.Add(e.Name, true);
+ try
+ {
+ IDesignerSerializationManager manager = (IDesignerSerializationManager)sender;
+ if (ResolveName(manager, e.Name, false))
+ {
+ e.Value = manager.GetInstance(e.Name);
+ }
+ }
+ finally
+ {
+ _nameResolveGuard.Remove(e.Name);
+ }
+ }
+
+ private void DeserializeDefaultProperties(IDesignerSerializationManager manager, string name, object state)
+ {
+ // Next, default properties, but only if we successfully resolved.
+ if (state != null && _applyDefaults)
+ {
+ object comp = manager.GetInstance(name);
+ if (comp != null)
+ {
+ PropertyDescriptorCollection props = TypeDescriptor.GetProperties(comp);
+ string[] defProps = (string[])state;
+ foreach (string propName in defProps)
+ {
+ PropertyDescriptor prop = props[propName];
+ if (prop != null && prop.CanResetValue(comp))
+ {
+ Trace("Resetting default for {0}.{1}", name, propName);
+ // If there is a member relationship setup for this property, we should disconnect it first. This makes sense, since if there was a previous relationship, we would have serialized it and not come here at all.
+ if (manager.GetService(typeof(MemberRelationshipService)) is MemberRelationshipService relationships && relationships[comp, prop] != MemberRelationship.Empty)
+ {
+ relationships[comp, prop] = MemberRelationship.Empty;
+ }
+ prop.ResetValue(comp);
+ }
+ }
+ }
+ }
+ }
+
+ private void DeserializeDesignTimeProperties(IDesignerSerializationManager manager, string name, object state)
+ {
+ if (state != null)
+ {
+ object comp = manager.GetInstance(name);
+ if (comp != null)
+ {
+ PropertyDescriptorCollection props = TypeDescriptor.GetProperties(comp);
+
+ foreach (DictionaryEntry de in (IDictionary)state)
+ {
+ PropertyDescriptor prop = props[(string)de.Key];
+ if (prop != null)
+ {
+ prop.SetValue(comp, de.Value);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// This is used to resolve nested component references. NestedComponents don't exist as sited components within the DesignerHost, they are actually sited within a parent component. This method takes the FullName defined on INestedSite and returns the component which matches it. outerComponent is the name of the topmost component which does exist in the DesignerHost
+ /// This code also exists in VSCodeDomDesignerLoader -- please keep them in sync.
+ ///
+ private IComponent ResolveNestedName(IDesignerSerializationManager manager, string name, ref string outerComponent)
+ {
+ IComponent curComp = null;
+ if (name != null && manager != null)
+ {
+ bool moreChunks = true;
+ Debug.Assert(name.IndexOf('.') > 0, "ResolvedNestedName accepts only nested names!");
+ // We need to resolve the first chunk using the manager. other chunks will be resolved within the nested containers.
+ int firstIndex = name.IndexOf('.', 0);
+ outerComponent = name.Substring(0, firstIndex);
+ curComp = manager.GetInstance(outerComponent) as IComponent;
+
+ int prevIndex = firstIndex;
+ int curIndex = name.IndexOf('.', firstIndex + 1);
+ while (moreChunks)
+ {
+ moreChunks = curIndex != -1;
+ string compName = moreChunks ? name.Substring(prevIndex + 1, curIndex) : name.Substring(prevIndex + 1);
+ if (curComp != null && curComp.Site != null)
+ {
+ ISite site = curComp.Site;
+ if (site.GetService(typeof(INestedContainer)) is INestedContainer container && !string.IsNullOrEmpty(compName))
+ {
+ curComp = container.Components[compName];
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ {
+ return null;
+ }
+
+ if (moreChunks)
+ {
+ prevIndex = curIndex;
+ curIndex = name.IndexOf('.', curIndex + 1);
+ }
+ }
+ }
+ return curComp;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
+ private bool ResolveName(IDesignerSerializationManager manager, string name, bool canInvokeManager)
+ {
+ bool resolved = false;
+ object[] state = (object[])_objectState[name];
+ // Check for a nested name. Components that are sited within NestedContainers need to be looked up in their nested container, and won't be resolvable directly via the manager.
+ if (name.IndexOf('.') > 0)
+ {
+ string parentName = null;
+ IComponent nestedComp = ResolveNestedName(manager, name, ref parentName);
+ if (nestedComp != null && parentName != null)
+ {
+ manager.SetName(nestedComp, name);
+ // What is the point of this? Well, the nested components won't be in the statement table with its nested name. However, their most parent component will be, so forcing a resolve of their name will actually deserialize the nested statements.
+ ResolveName(manager, parentName, canInvokeManager);
+ }
+ else
+ {
+ Debug.Fail("Unable to resolve nested component: " + name);
+ }
+ }
+
+ // First we check to see if the statements table contains an OrderedCodeStatementCollection for this name. If it does this means we have not resolved this name yet, so we grab its OrderedCodeStatementCollection and deserialize that, along with any default properties and design-time properties.
+ // If it doesn't contain an OrderedCodeStatementsCollection this means one of two things:
+ // 1. We already resolved this name and shoved an instance in there. In this case we just return the instance
+ // 2. There are no statements corresponding to this name, but there might be expressions that have never been deserialized, so we check for that and deserailize those.
+ if (_statementsTable[name] is OrderedCodeStatementCollection statements)
+ {
+ _objectState[name] = null;
+ _statementsTable[name] = null; // prevent recursion
+ // we look through the statements to find the variableRef or fieldRef that matches this name
+ string typeName = null;
+ foreach (CodeStatement statement in statements)
+ {
+ if (statement is CodeVariableDeclarationStatement cvds)
+ {
+ typeName = cvds.Type.BaseType;
+ break;
+ }
+ }
+
+ // next, invoke the serializer for this component
+ if (typeName != null)
+ {
+ Type type = manager.GetType(typeName);
+ if (type == null)
+ {
+ TraceError("Type does not exist: {0}", typeName);
+ manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerTypeNotFound, typeName), manager));
+ }
+ else
+ {
+ if (statements != null && statements.Count > 0)
+ {
+ CodeDomSerializer serializer = GetSerializer(manager, type);
+ if (serializer == null)
+ {
+ // We report this as an error. This indicates that there are code statements in initialize component that we do not know how to load.
+ TraceError("Type referenced in init method has no serializer: {0}", type.Name);
+ manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerNoSerializerForComponent, type.FullName), manager));
+ }
+ else
+ {
+ Trace("--------------------------------------------------------------------");
+ Trace(" Beginning deserialization of {0}", name);
+ Trace("--------------------------------------------------------------------");
+ try
+ {
+ object instance = serializer.Deserialize(manager, statements);
+ resolved = instance != null;
+ if (resolved)
+ {
+ _statementsTable[name] = instance;
+ }
+ }
+ catch (Exception ex)
+ {
+ manager.ReportError(ex);
+ }
+ }
+ }
+ }
+ }
+ // if we can't find a typeName to get a serializer with we fallback to deserializing each statement individually using the default serializer.
+ else
+ {
+ foreach (CodeStatement cs in statements)
+ {
+ DeserializeStatement(manager, cs);
+ }
+ resolved = true;
+ }
+
+ if (state != null && state[StateProperties] != null)
+ {
+ DeserializeDefaultProperties(manager, name, state[StateProperties]);
+ }
+
+ if (state != null && state[StateResources] != null)
+ {
+ DeserializeDesignTimeProperties(manager, name, state[StateResources]);
+ }
+
+ if (state != null && state[StateEvents] != null)
+ {
+ DeserializeEventResets(manager, name, state[StateEvents]);
+ }
+
+ if (state != null && state[StateModifier] != null)
+ {
+ DeserializeModifier(manager, name, state[StateModifier]);
+ }
+
+ if (_expressions.ContainsKey(name))
+ {
+ ArrayList exps = _expressions[name];
+ foreach (CodeExpression exp in exps)
+ {
+ object exValue = DeserializeExpression(manager, name, exp);
+ }
+ _expressions.Remove(name);
+ resolved = true;
+ }
+ }
+ else
+ {
+ resolved = _statementsTable[name] != null;
+ if (!resolved)
+ {
+ // this is condition 2 of the comment at the start of this method.
+ if (_expressions.ContainsKey(name))
+ {
+ ArrayList exps = _expressions[name];
+ foreach (CodeExpression exp in exps)
+ {
+ object exValue = DeserializeExpression(manager, name, exp);
+ if (exValue != null && !resolved)
+ {
+ if (canInvokeManager && manager.GetInstance(name) == null)
+ {
+ manager.SetName(exValue, name);
+ resolved = true;
+ }
+ }
+ }
+ }
+
+ // Sometimes components won't be in either the statements table or the expressions table, for example, this occurs for resources during undo/redo. In these cases the component should be resolvable by the manager. Never do this when we have been asked by the serialization manager to resolve the name; otherwise we may infinitely recurse.
+ if (!resolved && canInvokeManager)
+ {
+ resolved = manager.GetInstance(name) != null;
+ }
+
+ // In this case we still need to correctly deserialize default properties & design-time only properties.
+ if (resolved && state != null && state[StateProperties] != null)
+ {
+ DeserializeDefaultProperties(manager, name, state[StateProperties]);
+ }
+
+ if (resolved && state != null && state[StateResources] != null)
+ {
+ DeserializeDesignTimeProperties(manager, name, state[StateResources]);
+ }
+
+ if (resolved && state != null && state[StateEvents] != null)
+ {
+ DeserializeEventResets(manager, name, state[StateEvents]);
+ }
+
+ if (resolved && state != null && state[StateModifier] != null)
+ {
+ DeserializeModifier(manager, name, state[StateModifier]);
+ }
+ }
+
+ if (!(resolved || (!resolved && !canInvokeManager)))
+ {
+ manager.ReportError(new CodeDomSerializerException(string.Format(SR.CodeDomComponentSerializationServiceDeserializationError, name), manager));
+ Debug.Fail("No statements or instance for name and no lone experssions: " + name);
+ }
+ }
+ return resolved;
+ }
+
+ private void DeserializeEventResets(IDesignerSerializationManager manager, string name, object state)
+ {
+ if (state is List eventNames && manager != null && !string.IsNullOrEmpty(name))
+ {
+ object comp = manager.GetInstance(name);
+ if (comp != null && manager.GetService(typeof(IEventBindingService)) is IEventBindingService ebs)
+ {
+ PropertyDescriptorCollection eventProps = ebs.GetEventProperties(TypeDescriptor.GetEvents(comp));
+ if (eventProps != null)
+ {
+ foreach (string eventName in eventNames)
+ {
+ PropertyDescriptor prop = eventProps[eventName];
+
+ if (prop != null)
+ {
+ prop.SetValue(comp, null);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static void DeserializeModifier(IDesignerSerializationManager manager, string name, object state)
+ {
+ Debug.Assert(state != null && state is MemberAttributes, "Attempting to deserialize a null modifier");
+ object comp = manager.GetInstance(name);
+ if (comp != null)
+ {
+ MemberAttributes modifierValue = (MemberAttributes)state;
+ PropertyDescriptor modifierProp = TypeDescriptor.GetProperties(comp)["Modifiers"];
+ if (modifierProp != null)
+ {
+ modifierProp.SetValue(comp, modifierValue);
+ }
+ }
+ }
+
+ public override object Serialize(IDesignerSerializationManager manager, object state)
+ {
+ throw new NotSupportedException();
+ }
+
+ //
+ // For everything in the serialization manager's container, we need a variable ref, just in case something that has changed has a reference to another object. We also must do this for everything that we are serializing that is not marked as EntireObject. Otherwise reference could leak and cause the entire object to be serialized.
+ //
+ internal void SetupVariableReferences(IDesignerSerializationManager manager, IContainer container, IDictionary objectData, IList shimObjectNames)
+ {
+ foreach (IComponent c in container.Components)
+ {
+ string name = TypeDescriptor.GetComponentName(c);
+ if (name != null && name.Length > 0)
+ {
+ bool needVar = true;
+ if (objectData.Contains(c) && ((ObjectData)objectData[c]).EntireObject)
+ {
+ needVar = false;
+ }
+
+ if (needVar)
+ {
+ CodeVariableReferenceExpression var = new CodeVariableReferenceExpression(name);
+ SetExpression(manager, c, var);
+ if (!shimObjectNames.Contains(name))
+ {
+ shimObjectNames.Add(name);
+ }
+
+ if (c.Site != null)
+ {
+ if (c.Site.GetService(typeof(INestedContainer)) is INestedContainer nested && nested.Components.Count > 0)
+ {
+ SetupVariableReferences(manager, nested, objectData, shimObjectNames);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Serializes the given set of objects (contained in objectData) into the given object state dictionary.
+ ///
+ internal void Serialize(IDesignerSerializationManager manager, IDictionary objectData, IDictionary objectState, IList shimObjectNames)
+ {
+ if (manager.GetService(typeof(IContainer)) is IContainer container)
+ {
+ SetupVariableReferences(manager, container, objectData, shimObjectNames);
+ }
+
+ // Next, save a statement collection for each object.
+ StatementContext statementCxt = new StatementContext();
+ statementCxt.StatementCollection.Populate(objectData.Keys);
+ manager.Context.Push(statementCxt);
+ try
+ {
+ foreach (ObjectData data in objectData.Values)
+ {
+ CodeDomSerializer serializer = (CodeDomSerializer)manager.GetSerializer(data._value.GetType(), typeof(CodeDomSerializer));
+ // Saved state. Slot 0 is the code gen
+ // Slot 1 is for generated statements coming from the context.
+ // Slot 2 is an array of default properites.
+ // Slot 3 is for design time props.Any may be null.
+ // Slot 4 is for events that need to be reset.
+ // Slot 5 is for the modifier property of the object.
+ // Since it is DSV.Hidden, it won't be serialized. We special case it here.
+
+ object[] state = new object[6];
+ CodeStatementCollection extraStatements = new CodeStatementCollection();
+ manager.Context.Push(extraStatements);
+ if (serializer != null)
+ {
+ if (data.EntireObject)
+ {
+ if (!IsSerialized(manager, data._value))
+ {
+ if (data.Absolute)
+ {
+ state[StateCode] = serializer.SerializeAbsolute(manager, data._value);
+ }
+ else
+ {
+ state[StateCode] = serializer.Serialize(manager, data._value);
+ }
+ CodeStatementCollection ctxStatements = statementCxt.StatementCollection[data._value];
+ if (ctxStatements != null && ctxStatements.Count > 0)
+ {
+ state[StateCtx] = ctxStatements;
+ }
+
+ if (extraStatements.Count > 0)
+ {
+ if (state[StateCode] is CodeStatementCollection existingStatements)
+ {
+ existingStatements.AddRange(extraStatements);
+ }
+ }
+ }
+ else
+ {
+ state[StateCode] = statementCxt.StatementCollection[data._value];
+ }
+ }
+ else
+ {
+ CodeStatementCollection codeStatements = new CodeStatementCollection();
+ foreach (MemberData md in data.Members)
+ {
+ if (md._member.Attributes.Contains(DesignOnlyAttribute.Yes))
+ {
+ // For design time properties, we write their value into a resource blob.
+ if (md._member is PropertyDescriptor prop && prop.PropertyType.IsSerializable)
+ {
+ if (state[StateResources] == null)
+ {
+ state[StateResources] = new Hashtable();
+ }
+ ((Hashtable)state[StateResources])[prop.Name] = prop.GetValue(data._value);
+ }
+ }
+ else
+ {
+ if (md._absolute)
+ {
+ codeStatements.AddRange(serializer.SerializeMemberAbsolute(manager, data._value, md._member));
+ }
+ else
+ {
+ codeStatements.AddRange(serializer.SerializeMember(manager, data._value, md._member));
+ }
+ }
+ }
+ state[StateCode] = codeStatements;
+ }
+ }
+
+ if (extraStatements.Count > 0)
+ {
+ if (state[StateCode] is CodeStatementCollection existingStatements)
+ {
+ existingStatements.AddRange(extraStatements);
+ }
+ }
+
+ manager.Context.Pop();
+ // And now search for default properties and events
+ ArrayList defaultPropList = null;
+ List defaultEventList = null;
+ IEventBindingService ebs = manager.GetService(typeof(IEventBindingService)) as IEventBindingService;
+ Debug.Assert(ebs != null, "No IEventBindingService is available. Events will not be serialized correctly");
+ if (data.EntireObject)
+ {
+ PropertyDescriptorCollection props = TypeDescriptor.GetProperties(data._value);
+ foreach (PropertyDescriptor prop in props)
+ {
+ if (!prop.ShouldSerializeValue(data._value)
+ && !prop.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden))
+ {
+ if (prop.Attributes.Contains(DesignerSerializationVisibilityAttribute.Content) || !prop.IsReadOnly)
+ {
+ if (defaultPropList == null)
+ {
+ defaultPropList = new ArrayList(data.Members.Count);
+ }
+ Trace("Adding default for {0}.{1}", data._name, prop.Name);
+ defaultPropList.Add(prop.Name);
+ }
+ }
+ }
+
+ if (ebs != null)
+ {
+ PropertyDescriptorCollection events = ebs.GetEventProperties(TypeDescriptor.GetEvents(data._value));
+ foreach (PropertyDescriptor eventProp in events)
+ {
+ if (eventProp == null || eventProp.IsReadOnly)
+ {
+ continue;
+ }
+
+ if (eventProp.GetValue(data._value) == null)
+ {
+ if (defaultEventList == null)
+ {
+ defaultEventList = new List();
+ }
+ defaultEventList.Add(eventProp.Name);
+ }
+ }
+ }
+ }
+ else
+ {
+ foreach (MemberData md in data.Members)
+ {
+ if (md._member is PropertyDescriptor prop && !prop.ShouldSerializeValue(data._value))
+ {
+ if (ebs != null && ebs.GetEvent(prop) != null)
+ {
+ Debug.Assert(prop.GetValue(data._value) == null, "ShouldSerializeValue and GetValue are differing");
+ if (defaultEventList == null)
+ {
+ defaultEventList = new List();
+ }
+ defaultEventList.Add(prop.Name);
+ }
+ else
+ {
+ if (defaultPropList == null)
+ {
+ defaultPropList = new ArrayList(data.Members.Count);
+ }
+ Trace("Adding default for {0}.{1}", data._name, prop.Name);
+ defaultPropList.Add(prop.Name);
+ }
+ }
+ }
+ }
+
+ // Check for non-default modifiers property
+ if (TypeDescriptor.GetProperties(data._value)["Modifiers"] is PropertyDescriptor modifier)
+ {
+ state[StateModifier] = modifier.GetValue(data._value);
+ }
+
+ if (defaultPropList != null)
+ {
+ state[StateProperties] = (string[])defaultPropList.ToArray(typeof(string));
+ }
+
+ if (defaultEventList != null)
+ {
+ state[StateEvents] = defaultEventList;
+ }
+
+ if (state[StateCode] != null || state[StateProperties] != null)
+ {
+ objectState[data._name] = state;
+ }
+ }
+ }
+ finally
+ {
+ Debug.Assert(manager.Context.Current == statementCxt, "Context stack corrupted");
+ manager.Context.Pop();
+ }
+ }
+ }
+
+ ///
+ /// We create one of these for each specific member on an object.
+ ///
+ private class MemberData
+ {
+ ///
+ /// The member we're serializing.
+ ///
+ internal MemberDescriptor _member;
+
+ ///
+ /// True if we should try to serialize values that contain their defaults as well.
+ ///
+ internal bool _absolute;
+
+ ///
+ /// Creates a new member data ready to be serialized.
+ ///
+ internal MemberData(MemberDescriptor member, bool absolute)
+ {
+ _member = member;
+ _absolute = absolute;
+ }
+ }
+
+ ///
+ /// We create one of these for each object we process.
+ ///
+ private class ObjectData
+ {
+ private bool _entireObject;
+ private bool _absolute;
+ private ArrayList _members;
+
+ ///
+ /// The object value we're serializing.
+ ///
+ internal object _value;
+
+ ///
+ /// The name of the object we're serializing.
+ ///
+ internal string _name;
+
+ ///
+ /// If true, the entire object should be serialized. If false, only the members in the member list should be serialized.
+ ///
+ internal bool EntireObject
+ {
+ get => _entireObject;
+ set
+ {
+ if (value && _members != null)
+ {
+ _members.Clear();
+ }
+ _entireObject = value;
+ }
+ }
+
+ ///
+ /// If true, the object should be serialized such that during deserialization to an existing object the object is reconstructed entirely. If false, serialize normally
+ ///
+ internal bool Absolute
+ {
+ get => _absolute;
+ set => _absolute = value;
+ }
+
+ ///
+ /// A list of MemberData objects representing specific members that should be serialized.
+ ///
+ internal IList Members
+ {
+ get
+ {
+ if (_members == null)
+ {
+ _members = new ArrayList();
+ }
+ return _members;
+ }
+ }
+ }
+
+ ///
+ /// Our private resource manager...it just pushes all the data into a hashtable and then we serialize the hashtable. On deseriaization, the hashtable is rebuilt for us and we have all the data we saved out.
+ ///
+ private class LocalResourceManager : ResourceManager, IResourceWriter, IResourceReader
+ {
+ private Hashtable _hashtable;
+
+ internal LocalResourceManager() { }
+ internal LocalResourceManager(Hashtable data) { _hashtable = data; }
+
+ internal Hashtable Data
+ {
+ get
+ {
+ if (_hashtable == null)
+ {
+ _hashtable = new Hashtable();
+ }
+ return _hashtable;
+ }
+ }
+
+ // IResourceWriter
+ public void AddResource(string name, object value) { Data[name] = value; }
+ public void AddResource(string name, string value) { Data[name] = value; }
+ public void AddResource(string name, byte[] value) { Data[name] = value; }
+ public void Close() { }
+ public void Dispose() { Data.Clear(); }
+ public void Generate() { }
+
+ // IResourceReader / ResourceManager
+ public override object GetObject(string name) { return Data[name]; }
+ public override string GetString(string name) { return Data[name] as string; }
+ public IDictionaryEnumerator GetEnumerator() { return Data.GetEnumerator(); }
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+
+ ///
+ /// LocalServices contains the services that we add to our serialization manager. We do this, rather than implement interfaces directly on CodeDomSerializationStore to prevent people from assuming what our implementation is (CodeDomSerializationStore is returned publicly as SerializationStore).
+ ///
+ private class LocalServices : IServiceProvider, IResourceService
+ {
+
+ private readonly CodeDomSerializationStore _store;
+ private readonly IServiceProvider _provider;
+
+ internal LocalServices(CodeDomSerializationStore store, IServiceProvider provider)
+ {
+ _store = store;
+ _provider = provider;
+ }
+
+ // IResourceService
+ IResourceReader IResourceService.GetResourceReader(CultureInfo info) { return _store.Resources; }
+ IResourceWriter IResourceService.GetResourceWriter(CultureInfo info) { return _store.Resources; }
+
+ // IServiceProvider
+ object IServiceProvider.GetService(Type serviceType)
+ {
+ if (serviceType == null)
+ {
+ throw new ArgumentNullException(nameof(serviceType));
+ }
+
+ if (serviceType == typeof(IResourceService))
+ {
+ return this;
+ }
+
+ if (_provider != null)
+ {
+ return _provider.GetService(serviceType);
+ }
+ return null;
+ }
+ }
+
+ private class PassThroughSerializationManager : IDesignerSerializationManager
+ {
+ readonly Hashtable _resolved = new Hashtable();
+ readonly DesignerSerializationManager _manager;
+ private ResolveNameEventHandler _resolveNameEventHandler;
+
+ public PassThroughSerializationManager(DesignerSerializationManager manager) => _manager = manager;
+
+ public DesignerSerializationManager Manager
+ {
+ get => _manager;
+ }
+
+ ContextStack IDesignerSerializationManager.Context
+ {
+ get => ((IDesignerSerializationManager)_manager).Context;
+ }
+
+ PropertyDescriptorCollection IDesignerSerializationManager.Properties
+ {
+ get => ((IDesignerSerializationManager)_manager).Properties;
+ }
+
+ event ResolveNameEventHandler IDesignerSerializationManager.ResolveName
+ {
+ add
+ {
+ ((IDesignerSerializationManager)_manager).ResolveName += value;
+ _resolveNameEventHandler += value;
+ }
+ remove
+ {
+ ((IDesignerSerializationManager)_manager).ResolveName -= value;
+ _resolveNameEventHandler -= value;
+ }
+ }
+
+ event EventHandler IDesignerSerializationManager.SerializationComplete
+ {
+ add
+ {
+ ((IDesignerSerializationManager)_manager).SerializationComplete += value;
+ }
+ remove
+ {
+ ((IDesignerSerializationManager)_manager).SerializationComplete -= value;
+ }
+ }
+
+ void IDesignerSerializationManager.AddSerializationProvider(IDesignerSerializationProvider provider)
+ {
+ ((IDesignerSerializationManager)_manager).AddSerializationProvider(provider);
+ }
+
+ object IDesignerSerializationManager.CreateInstance(Type type, ICollection arguments, string name, bool addToContainer)
+ {
+ return ((IDesignerSerializationManager)_manager).CreateInstance(type, arguments, name, addToContainer);
+ }
+
+ object IDesignerSerializationManager.GetInstance(string name)
+ {
+ object instance = ((IDesignerSerializationManager)_manager).GetInstance(name);
+
+ // If an object is retrived from the current container as a result of GetInstance(), we need to make sure and fully deserialize it before returning it. To do this, we will force a resolve on this name and not interfere the next time GetInstance() is called with this component. This will force the component to completely deserialize.
+ if (_resolveNameEventHandler != null && instance != null && !_resolved.ContainsKey(name) &&
+ _manager.PreserveNames && _manager.Container != null && _manager.Container.Components[name] != null)
+ {
+ _resolved[name] = true;
+ _resolveNameEventHandler(this, new ResolveNameEventArgs(name));
+ }
+ return instance;
+ }
+
+ string IDesignerSerializationManager.GetName(object value)
+ {
+ return ((IDesignerSerializationManager)_manager).GetName(value);
+ }
+
+ object IDesignerSerializationManager.GetSerializer(Type objectType, Type serializerType)
+ {
+ return ((IDesignerSerializationManager)_manager).GetSerializer(objectType, serializerType);
+ }
+
+ Type IDesignerSerializationManager.GetType(string typeName)
+ {
+ return ((IDesignerSerializationManager)_manager).GetType(typeName);
+ }
+
+ void IDesignerSerializationManager.RemoveSerializationProvider(IDesignerSerializationProvider provider)
+ {
+ ((IDesignerSerializationManager)_manager).RemoveSerializationProvider(provider);
+ }
+
+ void IDesignerSerializationManager.ReportError(object errorInformation)
+ {
+ ((IDesignerSerializationManager)_manager).ReportError(errorInformation);
+ }
+
+ void IDesignerSerializationManager.SetName(object instance, string name)
+ {
+ ((IDesignerSerializationManager)_manager).SetName(instance, name);
+ }
+
+ object IServiceProvider.GetService(Type serviceType)
+ {
+ return ((IDesignerSerializationManager)_manager).GetService(serviceType);
+ }
+
+ }
+
+ ///
+ /// This is a serialzation manager that can load assemblies and search for types and provide a resource manager from our serialization store.
+ ///
+ private class LocalDesignerSerializationManager : DesignerSerializationManager
+ {
+ private readonly CodeDomSerializationStore _store;
+ private Nullable _typeSvcAvailable = new Nullable();
+
+ ///
+ /// Creates a new serilalization manager.
+ ///
+ internal LocalDesignerSerializationManager(CodeDomSerializationStore store, IServiceProvider provider) : base(provider)
+ {
+ _store = store;
+ }
+
+ ///
+ /// We override CreateInstance here to provide a hook to our resource manager.
+ ///
+ protected override object CreateInstance(Type type, ICollection arguments, string name, bool addToContainer)
+ {
+ if (typeof(ResourceManager).IsAssignableFrom(type))
+ {
+ return _store.Resources;
+ }
+ return base.CreateInstance(type, arguments, name, addToContainer);
+ }
+
+ private Nullable TypeResolutionAvailable
+ {
+ get
+ {
+ if (!_typeSvcAvailable.HasValue)
+ {
+ _typeSvcAvailable = new Nullable(GetService(typeof(ITypeResolutionService)) != null);
+ }
+ return _typeSvcAvailable.Value;
+ }
+ }
+
+ ///
+ /// Override of GetType. We favor the base implementation first, which uses the type resolution service if it is available. If that fails, we will try to load assemblies from the given array of assembly names.
+ ///
+ protected override Type GetType(string name)
+ {
+ Type t = base.GetType(name);
+ if (t == null && !TypeResolutionAvailable.Value)
+ {
+ AssemblyName[] names = _store.AssemblyNames;
+ // First try the assembly names directly.
+ foreach (AssemblyName n in names)
+ {
+ Assembly a = Assembly.Load(n);
+ if (a != null)
+ {
+ t = a.GetType(name);
+ if (t != null)
+ {
+ break;
+ }
+ }
+ }
+
+ // Failing that go after their dependencies.
+ if (t == null)
+ {
+ foreach (AssemblyName n in names)
+ {
+ Assembly a = Assembly.Load(n);
+ if (a != null)
+ {
+ foreach (AssemblyName dep in a.GetReferencedAssemblies())
+ {
+ Assembly aDep = Assembly.Load(dep);
+ if (aDep != null)
+ {
+ t = aDep.GetType(name);
+ if (t != null)
+ {
+ break;
+ }
+ }
+ }
+ if (t != null)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return t;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializer.cs
index 7c095318fe6..c995e73f452 100644
--- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializer.cs
+++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializer.cs
@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
using System.CodeDom;
+using System.Diagnostics;
+using System.Globalization;
namespace System.ComponentModel.Design.Serialization
{
@@ -13,16 +15,28 @@ namespace System.ComponentModel.Design.Serialization
[DefaultSerializationProvider(typeof(CodeDomSerializationProvider))]
public class CodeDomSerializer : CodeDomSerializerBase
{
+ private static readonly Attribute[] _runTimeFilter = new Attribute[] { DesignOnlyAttribute.No };
+ private static readonly Attribute[] _designTimeFilter = new Attribute[] { DesignOnlyAttribute.Yes };
+ private static CodeThisReferenceExpression _thisRef = new CodeThisReferenceExpression();
+
///
/// Determines which statement group the given statement should belong to. The expression parameter
/// is an expression that the statement has been reduced to, and targetType represents the type
/// of this statement. This method returns the name of the component this statement should be grouped
/// with.
///
- public virtual string GetTargetComponentName(CodeStatement statement, CodeExpression expression,
- Type targetType)
+ public virtual string GetTargetComponentName(CodeStatement statement, CodeExpression expression, Type targetType)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ string name = null;
+ if (expression is CodeVariableReferenceExpression variableReferenceEx)
+ {
+ name = variableReferenceEx.VariableName;
+ }
+ else if (expression is CodeFieldReferenceExpression fieldReferenceEx)
+ {
+ name = fieldReferenceEx.FieldName;
+ }
+ return name;
}
///
@@ -32,7 +46,61 @@ public virtual string GetTargetComponentName(CodeStatement statement, CodeExpres
///
public virtual object Deserialize(IDesignerSerializationManager manager, object codeObject)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ object instance = null;
+ if (manager == null || codeObject == null)
+ {
+ throw new ArgumentNullException(manager == null ? "manager" : "codeObject");
+ }
+
+ using (TraceScope("CodeDomSerializer::Deserialize"))
+ {
+ // What is the code object? We support an expression, a statement or a collection of statements
+ if (codeObject is CodeExpression expression)
+ {
+ instance = DeserializeExpression(manager, null, expression);
+ }
+ else
+ {
+ if (codeObject is CodeStatementCollection statements)
+ {
+ foreach (CodeStatement element in statements)
+ {
+ // If we do not yet have an instance, we will need to pick through the statements and see if we can find one.
+ if (instance == null)
+ {
+ instance = DeserializeStatementToInstance(manager, element);
+ if (instance != null)
+ {
+ PropertyDescriptorCollection props = TypeDescriptor.GetProperties(instance, new Attribute[] { BrowsableAttribute.Yes });
+ foreach (PropertyDescriptor prop in props)
+ {
+ if (!prop.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden) &&
+ prop.Attributes.Contains(DesignerSerializationVisibilityAttribute.Content) &&
+ !(manager.GetSerializer(prop.PropertyType, typeof(CodeDomSerializer)) is CollectionCodeDomSerializer))
+ {
+ ResetBrowsableProperties(prop.GetValue(instance));
+ }
+ }
+ }
+ }
+ else
+ {
+ DeserializeStatement(manager, element);
+ }
+ }
+ }
+ else
+ {
+ if (!(codeObject is CodeStatement statement))
+ {
+ Debug.Fail("CodeDomSerializer::Deserialize requires a CodeExpression, CodeStatement or CodeStatementCollection to parse");
+ string supportedTypes = string.Format(CultureInfo.CurrentCulture, "{0}, {1}, {2}", typeof(CodeExpression).Name, typeof(CodeStatement).Name, typeof(CodeStatementCollection).Name);
+ throw new ArgumentException(string.Format(SR.SerializerBadElementTypes, codeObject.GetType().Name, supportedTypes));
+ }
+ }
+ }
+ }
+ return instance;
}
///
@@ -43,7 +111,38 @@ public virtual object Deserialize(IDesignerSerializationManager manager, object
///
protected object DeserializeStatementToInstance(IDesignerSerializationManager manager, CodeStatement statement)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ object instance = null;
+ if (statement is CodeAssignStatement assign)
+ {
+ if (assign.Left is CodeFieldReferenceExpression fieldRef)
+ {
+ Trace("Assigning instance to field {0}", fieldRef.FieldName);
+ instance = DeserializeExpression(manager, fieldRef.FieldName, assign.Right);
+ }
+ else
+ {
+ if (assign.Left is CodeVariableReferenceExpression varRef)
+ {
+ Trace("Assigning instance to variable {0}", varRef.VariableName);
+ instance = DeserializeExpression(manager, varRef.VariableName, assign.Right);
+ }
+ else
+ {
+ DeserializeStatement(manager, assign);
+ }
+ }
+ }
+ else if (statement is CodeVariableDeclarationStatement varDecl && varDecl.InitExpression != null)
+ {
+ Trace("Initializing variable declaration for variable {0}", varDecl.Name);
+ instance = DeserializeExpression(manager, varDecl.Name, varDecl.InitExpression);
+ }
+ else
+ {
+ // This statement isn't one that will return a named object. Deserialize it normally.
+ DeserializeStatement(manager, statement);
+ }
+ return instance;
}
///
@@ -51,7 +150,79 @@ protected object DeserializeStatementToInstance(IDesignerSerializationManager ma
///
public virtual object Serialize(IDesignerSerializationManager manager, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ object result = null;
+ if (manager == null || value == null) throw new ArgumentNullException(manager == null ? "manager" : "value");
+
+ using (TraceScope("CodeDomSerializer::Serialize"))
+ {
+ Trace("Type: {0}", value.GetType().Name);
+
+ if (value is Type)
+ {
+ result = new CodeTypeOfExpression((Type)value);
+ }
+ else
+ {
+ bool isComplete = false;
+ bool isPreset;
+ CodeExpression expression = SerializeCreationExpression(manager, value, out bool isCompleteExpression);
+ // if the object is not a component we will honor the return value from SerializeCreationExpression. For compat reasons we ignore the value if the object is a component.
+ if (!(value is IComponent))
+ {
+ isComplete = isCompleteExpression;
+ }
+
+ // We need to find out if SerializeCreationExpression returned a preset expression.
+ if (manager.Context[typeof(ExpressionContext)] is ExpressionContext cxt && object.ReferenceEquals(cxt.PresetValue, value))
+ {
+ isPreset = true;
+ }
+ else
+ {
+ isPreset = false;
+ }
+
+ TraceIf(expression == null, "Unable to create object; aborting.");
+ // Short circuit common cases
+ if (expression != null)
+ {
+ if (isComplete)
+ {
+ Trace("Single expression : {0}", expression);
+ result = expression;
+ }
+ else
+ {
+ // Ok, we have an incomplete expression. That means we've created the object but we will need to set properties on it to configure it. Therefore, we need to have a variable reference to it unless we were given a preset expression already.
+ CodeStatementCollection statements = new CodeStatementCollection();
+
+ if (isPreset)
+ {
+ SetExpression(manager, value, expression, true);
+ }
+ else
+ {
+ CodeExpression variableReference;
+ string varName = GetUniqueName(manager, value);
+ string varTypeName = TypeDescriptor.GetClassName(value);
+
+ CodeVariableDeclarationStatement varDecl = new CodeVariableDeclarationStatement(varTypeName, varName);
+ Trace("Generating local : {0}", varName);
+ varDecl.InitExpression = expression;
+ statements.Add(varDecl);
+ variableReference = new CodeVariableReferenceExpression(varName);
+ SetExpression(manager, value, variableReference);
+ }
+ // Finally, we need to walk properties and events for this object
+ SerializePropertiesToResources(manager, statements, value, _designTimeFilter);
+ SerializeProperties(manager, statements, value, _runTimeFilter);
+ SerializeEvents(manager, statements, value, _runTimeFilter);
+ result = statements;
+ }
+ }
+ }
+ }
+ return result;
}
///
@@ -59,25 +230,81 @@ public virtual object Serialize(IDesignerSerializationManager manager, object va
///
public virtual object SerializeAbsolute(IDesignerSerializationManager manager, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ object data;
+ SerializeAbsoluteContext abs = new SerializeAbsoluteContext();
+ manager.Context.Push(abs);
+ try
+ {
+ data = Serialize(manager, value);
+ }
+ finally
+ {
+ Debug.Assert(manager.Context.Current == abs, "Serializer added a context it didn't remove.");
+ manager.Context.Pop();
+ }
+ return data;
}
///
/// This serializes the given member on the given object.
///
- public virtual CodeStatementCollection SerializeMember(IDesignerSerializationManager manager,
- object owningObject, MemberDescriptor member)
+ public virtual CodeStatementCollection SerializeMember(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (owningObject == null) throw new ArgumentNullException("owningObject");
+ if (member == null) throw new ArgumentNullException("member");
+
+ CodeStatementCollection statements = new CodeStatementCollection();
+ // See if we have an existing expression for this member. If not, fabricate one
+ CodeExpression expression = GetExpression(manager, owningObject);
+ if (expression == null)
+ {
+ string name = GetUniqueName(manager, owningObject);
+ expression = new CodeVariableReferenceExpression(name);
+ SetExpression(manager, owningObject, expression);
+ }
+
+ if (member is PropertyDescriptor property)
+ {
+ SerializeProperty(manager, statements, owningObject, property);
+ }
+ else
+ {
+ if (member is EventDescriptor evt)
+ {
+ SerializeEvent(manager, statements, owningObject, evt);
+ }
+ else
+ {
+ throw new NotSupportedException(string.Format(SR.SerializerMemberTypeNotSerializable, member.GetType().FullName));
+ }
+ }
+ return statements;
}
///
/// This serializes the given member on the given object.
///
- public virtual CodeStatementCollection SerializeMemberAbsolute(IDesignerSerializationManager manager,
- object owningObject, MemberDescriptor member)
+ public virtual CodeStatementCollection SerializeMemberAbsolute(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (owningObject == null) throw new ArgumentNullException("owningObject");
+ if (member == null) throw new ArgumentNullException("member");
+
+ CodeStatementCollection statements;
+ SerializeAbsoluteContext abs = new SerializeAbsoluteContext(member);
+ manager.Context.Push(abs);
+
+ try
+ {
+ statements = SerializeMember(manager, owningObject, member);
+ }
+ finally
+ {
+ Debug.Assert(manager.Context.Current == abs, "Serializer added a context it didn't remove.");
+ manager.Context.Pop();
+ }
+ return statements;
}
///
@@ -87,11 +314,82 @@ public virtual CodeStatementCollection SerializeMemberAbsolute(IDesignerSerializ
/// when you expect the resulting expression to be used as a parameter or target
/// of a statement.
///
- [Obsolete(
- "This method has been deprecated. Use SerializeToExpression or GetExpression instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ [Obsolete("This method has been deprecated. Use SerializeToExpression or GetExpression instead. http://go.microsoft.com/fwlink/?linkid=14202")]
protected CodeExpression SerializeToReferenceExpression(IDesignerSerializationManager manager, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ CodeExpression expression = null;
+ using (TraceScope("CodeDomSerializer::SerializeToReferenceExpression"))
+ {
+ // First - try GetExpression
+ expression = GetExpression(manager, value);
+ // Next, we check for a named IComponent, and return a reference to it.
+ if (expression == null && value is IComponent)
+ {
+ string name = manager.GetName(value);
+ bool referenceName = false;
+ if (name == null)
+ {
+ IReferenceService referenceService = (IReferenceService)manager.GetService(typeof(IReferenceService));
+ if (referenceService != null)
+ {
+ name = referenceService.GetName(value);
+ referenceName = name != null;
+ }
+ }
+
+ if (name != null)
+ {
+ Trace("Object is reference ({0}) Creating reference expression", name);
+ // Check to see if this is a reference to the root component. If it is, then use "this".
+ RootContext root = (RootContext)manager.Context[typeof(RootContext)];
+ if (root != null && root.Value == value)
+ {
+ expression = root.Expression;
+ }
+ else if (referenceName && name.IndexOf('.') != -1)
+ {
+ // if it's a reference name with a dot, we've actually got a property here...
+ int dotIndex = name.IndexOf('.');
+ expression = new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(_thisRef, name.Substring(0, dotIndex)), name.Substring(dotIndex + 1));
+ }
+ else
+ {
+ expression = new CodeFieldReferenceExpression(_thisRef, name);
+ }
+ }
+ }
+ }
+ return expression;
+ }
+ private void ResetBrowsableProperties(object instance)
+ {
+ if (instance == null)
+ {
+ return;
+ }
+
+ PropertyDescriptorCollection props = TypeDescriptor.GetProperties(instance, new Attribute[] { BrowsableAttribute.Yes });
+ foreach (PropertyDescriptor prop in props)
+ {
+ if (!prop.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden))
+ {
+ if (prop.CanResetValue(instance))
+ {
+ try
+ {
+ prop.ResetValue(instance);
+ }
+ catch (ArgumentException e)
+ {
+ Debug.Assert(false, e.Message);
+ }
+ }
+ else if (prop.Attributes.Contains(DesignerSerializationVisibilityAttribute.Content))
+ {
+ ResetBrowsableProperties(prop.GetValue(instance));
+ }
+ }
+ }
}
}
}
diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerBase.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerBase.cs
index 9dab795be83..cb71e079120 100644
--- a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerBase.cs
+++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerBase.cs
@@ -3,7 +3,13 @@
// See the LICENSE file in the project root for more information.
using System.CodeDom;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Reflection;
+using System.Text;
namespace System.ComponentModel.Design.Serialization
{
@@ -14,6 +20,11 @@ namespace System.ComponentModel.Design.Serialization
[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class CodeDomSerializerBase
{
+ private static readonly Attribute[] runTimeProperties = new Attribute[] { DesignOnlyAttribute.No };
+ private static readonly CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression();
+ private static TraceSwitch traceSerialization = new TraceSwitch("DesignerSerialization", "Trace design time serialization");
+ private static Stack traceScope;
+
///
/// Internal constructor so only we can derive from this class.
///
@@ -25,10 +36,68 @@ internal CodeDomSerializerBase()
/// 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. The default implementation invokes manager.CreateInstance.
///
- protected virtual object DeserializeInstance(IDesignerSerializationManager manager, Type type,
- object[] parameters, string name, bool addToContainer)
+ protected virtual object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (type == null) throw new ArgumentNullException("type");
+ return manager.CreateInstance(type, parameters, name, addToContainer);
+ }
+
+ ///
+ /// This routine returns the correct typename given a CodeTypeReference. It expands the child typenames
+ /// and builds up the clr formatted generic name. If its not a generic, it just returns BaseType.
+ ///
+ internal static string GetTypeNameFromCodeTypeReference(IDesignerSerializationManager manager, CodeTypeReference typeref)
+ {
+ //we do this to avoid an extra gettype for the usual nongeneric case.
+ if (typeref.TypeArguments == null || typeref.TypeArguments.Count == 0)
+ {
+ return typeref.BaseType;
+ }
+
+ return GetTypeNameFromCodeTypeReferenceHelper(manager, typeref);
+ }
+ private static string GetTypeNameFromCodeTypeReferenceHelper(IDesignerSerializationManager manager, CodeTypeReference typeref)
+ {
+ if (typeref.TypeArguments == null || typeref.TypeArguments.Count == 0)
+ {
+ Type t = manager.GetType(typeref.BaseType);
+ //we use the assemblyqualifiedname where we can so that GetType will find it correctly.
+ if (t != null)
+ {
+ // get type which exists in the target framework if any
+ return GetReflectionTypeFromTypeHelper(manager, t).AssemblyQualifiedName;
+ }
+ return typeref.BaseType;
+ }
+
+ //create the MyGeneric`2[ part
+ StringBuilder typename = new StringBuilder(typeref.BaseType);
+ if (!typeref.BaseType.Contains("`"))
+ {
+ typename.Append("`");
+ typename.Append(typeref.TypeArguments.Count);
+ }
+ typename.Append("[");
+
+ bool first = true;
+
+ //now create each sub-argument part.
+ foreach (CodeTypeReference childref in typeref.TypeArguments)
+ {
+ if (!first)
+ {
+ typename.Append(",");
+ }
+ typename.Append("[");
+ typename.Append(GetTypeNameFromCodeTypeReferenceHelper(manager, childref));
+ typename.Append("]");
+ first = false;
+ }
+ typename.Append("]");
+
+ //otherwise, we have a generic and we need to format it.
+ return typename.ToString();
}
///
@@ -36,7 +105,12 @@ protected virtual object DeserializeInstance(IDesignerSerializationManager manag
///
protected static TypeDescriptionProvider GetTargetFrameworkProvider(IServiceProvider provider, object instance)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ // service will be null outside the VisualStudio
+ if (provider.GetService(typeof(TypeDescriptionProviderService)) is TypeDescriptionProviderService service)
+ {
+ return service.GetProvider(instance);
+ }
+ return null;
}
///
@@ -44,11 +118,55 @@ protected static TypeDescriptionProvider GetTargetFrameworkProvider(IServiceProv
/// looked up on the target framerwork assembly. Be careful to not use mix
/// this type with runtime types in comparisons!
///
- [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification =
- "we pass serialization manager to Error")]
+ [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "we pass serialization manager to Error")]
protected static Type GetReflectionTypeFromTypeHelper(IDesignerSerializationManager manager, Type type)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (type == null || manager == null)
+ {
+ Debug.Fail("GetReflectionTypeFromTypeHelper does not accept null arguments.");
+ return null;
+ }
+
+ TypeDescriptionProvider targetProvider = GetTargetFrameworkProviderForType(manager, type);
+ if (targetProvider != null)
+ {
+ if (targetProvider.IsSupportedType(type))
+ {
+ return targetProvider.GetReflectionType(type);
+ }
+ Error(manager, string.Format(SR.TypeNotFoundInTargetFramework, type.FullName), SR.SerializerUndeclaredName);
+ }
+ return TypeDescriptor.GetReflectionType(type);
+ }
+
+ private static void Error(IDesignerSerializationManager manager, string exceptionText, string helpLink)
+ {
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (exceptionText == null) throw new ArgumentNullException("exceptionText");
+
+ CodeStatement statement = (CodeStatement)manager.Context[typeof(CodeStatement)];
+ CodeLinePragma linePragma = null;
+ if (statement != null)
+ {
+ linePragma = statement.LinePragma;
+ }
+
+ Exception exception = new CodeDomSerializerException(exceptionText, linePragma)
+ {
+ HelpLink = helpLink
+ };
+ throw exception;
+ }
+
+ private static TypeDescriptionProvider GetTargetFrameworkProviderForType(IServiceProvider provider, Type type)
+ {
+ TypeDescriptionProviderService service = provider.GetService(typeof(TypeDescriptionProviderService)) as TypeDescriptionProviderService;
+ // service will be null outside the VisualStudio
+ if (service != null)
+ {
+ return service.GetProvider(type);
+ }
+ return null;
}
///
@@ -57,11 +175,30 @@ protected static Type GetReflectionTypeFromTypeHelper(IDesignerSerializationMana
/// Never pass a type returned from GetReflectionType to runtime APIs that need a type.
/// Call GetRuntimeType first to unwrap the reflection type.
///
- [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification =
- "we pass serialization manager to Error")]
+ [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "we pass serialization manager to Error")]
protected static Type GetReflectionTypeHelper(IDesignerSerializationManager manager, object instance)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (instance == null || manager == null)
+ {
+ Debug.Fail("GetReflectionTypeHelper does not accept null arguments.");
+ return null;
+ }
+
+ Type type = instance.GetType();
+ if (type.IsValueType)
+ {
+ TypeDescriptionProvider targetProvider = GetTargetFrameworkProvider(manager, instance);
+ if (targetProvider != null)
+ {
+ if (targetProvider.IsSupportedType(type))
+ {
+ return targetProvider.GetReflectionType(instance);
+ }
+ Error(manager, string.Format(SR.TypeNotFoundInTargetFramework, instance.GetType().FullName), SR.SerializerUndeclaredName);
+ }
+ }
+
+ return TypeDescriptor.GetReflectionType(instance);
}
///
@@ -69,42 +206,155 @@ protected static Type GetReflectionTypeHelper(IDesignerSerializationManager mana
///
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification =
"we pass serialization manager to Error")]
- protected static PropertyDescriptorCollection GetPropertiesHelper(IDesignerSerializationManager manager,
- object instance, Attribute[] attributes)
+ protected static PropertyDescriptorCollection GetPropertiesHelper(IDesignerSerializationManager manager, object instance, Attribute[] attributes)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (instance == null || manager == null)
+ {
+ Debug.Fail("GetPropertiesHelper does not accept null arguments.");
+ return null;
+ }
+
+ if (instance.GetType().IsValueType)
+ {
+ TypeDescriptionProvider targetProvider = GetTargetFrameworkProvider(manager, instance);
+ if (targetProvider != null)
+ {
+ // target framework provider is null at runtime
+ if (targetProvider.IsSupportedType(instance.GetType()))
+ {
+ ICustomTypeDescriptor targetAwareDescriptor = targetProvider.GetTypeDescriptor(instance);
+ if (targetAwareDescriptor != null)
+ {
+ if (attributes == null)
+ {
+ return targetAwareDescriptor.GetProperties();
+ }
+ return targetAwareDescriptor.GetProperties(attributes);
+ }
+ }
+ else
+ {
+ Error(manager, string.Format(SR.TypeNotFoundInTargetFramework, instance.GetType().FullName), SR.SerializerUndeclaredName);
+ }
+ }
+ }
+
+ if (attributes == null)
+ {
+ return TypeDescriptor.GetProperties(instance);
+ }
+ return TypeDescriptor.GetProperties(instance, attributes);
}
///
/// Get events collection as defined in the project target framework
///
- [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification =
- "we pass serialization manager to Error")]
- protected static EventDescriptorCollection GetEventsHelper(IDesignerSerializationManager manager,
- object instance, Attribute[] attributes)
+ [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "we pass serialization manager to Error")]
+ protected static EventDescriptorCollection GetEventsHelper(IDesignerSerializationManager manager, object instance, Attribute[] attributes)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (instance == null || manager == null)
+ {
+ Debug.Fail("GetEventsHelper does not accept null arguments.");
+ return null;
+ }
+
+ if (instance.GetType().IsValueType)
+ {
+ TypeDescriptionProvider targetProvider = GetTargetFrameworkProvider(manager, instance);
+ if (targetProvider != null)
+ {
+ if (targetProvider.IsSupportedType(instance.GetType()))
+ {
+ ICustomTypeDescriptor targetAwareDescriptor = targetProvider.GetTypeDescriptor(instance);
+ if (targetAwareDescriptor != null)
+ {
+ if (attributes == null)
+ {
+ return targetAwareDescriptor.GetEvents();
+ }
+ return targetAwareDescriptor.GetEvents(attributes);
+ }
+ }
+ else
+ {
+ Error(manager, string.Format(SR.TypeNotFoundInTargetFramework, instance.GetType().FullName), SR.SerializerUndeclaredName);
+ }
+ }
+ }
+
+ if (attributes == null)
+ {
+ return TypeDescriptor.GetEvents(instance);
+ }
+
+ return TypeDescriptor.GetEvents(instance, attributes);
}
///
/// Get attributes collection as defined in the project target framework
///
- [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification =
- "we pass serialization manager to Error")]
+ [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "we pass serialization manager to Error")]
protected static AttributeCollection GetAttributesHelper(IDesignerSerializationManager manager, object instance)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (instance == null || manager == null)
+ {
+ Debug.Fail("GetAttributesHelper does not accept null arguments.");
+ return null;
+ }
+ if (instance.GetType().IsValueType)
+ {
+ TypeDescriptionProvider targetProvider = GetTargetFrameworkProvider(manager, instance);
+ if (targetProvider != null)
+ {
+ if (targetProvider.IsSupportedType(instance.GetType()))
+ {
+ ICustomTypeDescriptor targetAwareDescriptor = targetProvider.GetTypeDescriptor(instance);
+ if (targetAwareDescriptor != null)
+ {
+ return targetAwareDescriptor.GetAttributes();
+ }
+ }
+ else
+ {
+ Error(manager, string.Format(SR.TypeNotFoundInTargetFramework, instance.GetType().FullName), SR.SerializerUndeclaredName);
+ }
+ }
+ }
+ return TypeDescriptor.GetAttributes(instance);
}
///
/// Get attributes collection as defined in the project target framework
///
- [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification =
- "we pass serialization manager to Error")]
- protected static AttributeCollection GetAttributesFromTypeHelper(IDesignerSerializationManager manager,
- Type type)
+ [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "we pass serialization manager to Error")]
+ protected static AttributeCollection GetAttributesFromTypeHelper(IDesignerSerializationManager manager, Type type)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (type == null || manager == null)
+ {
+ Debug.Fail("GetAttributesFromTypeHelper does not accept null arguments.");
+ return null;
+ }
+
+ if (type.IsValueType)
+ {
+ TypeDescriptionProvider targetProvider = GetTargetFrameworkProviderForType(manager, type);
+ if (targetProvider != null)
+ {
+ if (targetProvider.IsSupportedType(type))
+ {
+ ICustomTypeDescriptor targetAwareDescriptor = targetProvider.GetTypeDescriptor(type);
+ if (targetAwareDescriptor != null)
+ {
+ return targetAwareDescriptor.GetAttributes();
+ }
+ }
+ else
+ {
+ Error(manager, string.Format(SR.TypeNotFoundInTargetFramework, type.FullName), SR.SerializerUndeclaredName);
+ }
+ }
+ }
+ return TypeDescriptor.GetAttributes(type);
}
///
@@ -113,10 +363,132 @@ protected static AttributeCollection GetAttributesFromTypeHelper(IDesignerSerial
/// in code, such as design-time properties.
///
[SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
- protected void DeserializePropertiesFromResources(IDesignerSerializationManager manager, object value,
- Attribute[] filter)
+ protected void DeserializePropertiesFromResources(IDesignerSerializationManager manager, object value, Attribute[] filter)
+ {
+ using (TraceScope("ComponentCodeDomSerializerBase::DeserializePropertiesFromResources"))
+ {
+ // It is much faster to dig through the resources first, and then map these resources to properties than it is to filter properties at each turn. Why? Because filtering properties requires a separate filter call for each object (because designers get a chance to filter, the cache is per-component), while resources are loaded once per document.
+ IDictionaryEnumerator de = ResourceCodeDomSerializer.GetDefault().GetMetadataEnumerator(manager);
+ if (de == null)
+ {
+ de = ResourceCodeDomSerializer.GetDefault().GetEnumerator(manager, CultureInfo.InvariantCulture);
+ }
+
+ if (de != null)
+ {
+ string ourObjectName;
+ if (manager.Context[typeof(RootContext)] is RootContext root && root.Value == value)
+ {
+ ourObjectName = "$this";
+ }
+ else
+ {
+ ourObjectName = manager.GetName(value);
+ }
+
+ PropertyDescriptorCollection ourProperties = GetPropertiesHelper(manager, value, null);
+ while (de.MoveNext())
+ {
+ string resourceName = de.Key as string;
+ Debug.Assert(resourceName != null, "non-string keys in dictionary entry");
+ int dotIndex = resourceName.IndexOf('.');
+ if (dotIndex == -1)
+ {
+ continue;
+ }
+
+ string objectName = resourceName.Substring(0, dotIndex);
+ // Skip now if this isn't a value for our object.
+ if (!objectName.Equals(ourObjectName))
+ {
+ continue;
+ }
+
+ string propertyName = resourceName.Substring(dotIndex + 1);
+
+ // Now locate the property by this name.
+ PropertyDescriptor property = ourProperties[propertyName];
+ if (property == null)
+ {
+ continue;
+ }
+
+ // This property must have matching attributes.
+ bool passFilter = true;
+ if (filter != null)
+ {
+ AttributeCollection propAttributes = property.Attributes;
+ foreach (Attribute a in filter)
+ {
+ if (!propAttributes.Contains(a))
+ {
+ passFilter = false;
+ break;
+ }
+ }
+ }
+
+ // If this property passes inspection, then set it.
+ if (passFilter)
+ {
+ object resourceObject = de.Value;
+ Trace("Resource: {0}, value: {1}", resourceName, (resourceObject == null ? "(null)" : resourceObject));
+ try
+ {
+ property.SetValue(value, resourceObject);
+ }
+ catch (Exception e)
+ {
+ manager.ReportError(e);
+ }
+ }
+ }
+ }
+ }
+ }
+ internal static IDisposable TraceScope(string name)
+ {
+ if (traceScope == null) traceScope = new Stack();
+#if DEBUG
+ Trace(name);
+ traceScope.Push(name);
+#endif
+ return new TracingScope();
+ }
+
+ [Conditional("DEBUG")]
+ internal static void TraceIf(bool condition, string message, params object[] values)
+ {
+ if (condition) Trace(message, values);
+ }
+
+ [Conditional("DEBUG")]
+ internal static void Trace(string message, params object[] values)
+ {
+ if (traceSerialization.TraceVerbose)
+ {
+ int indent = 0;
+ int oldIndent = Debug.IndentLevel;
+
+ if (traceScope != null) indent = traceScope.Count;
+ try
+ {
+ Debug.IndentLevel = indent;
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, message, values));
+ }
+ finally
+ {
+ Debug.IndentLevel = oldIndent;
+ }
+ }
+ }
+
+ private struct TracingScope : IDisposable
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ public void Dispose()
+ {
+ if (traceScope != null) traceScope.Pop();
+ }
}
///
@@ -126,7 +498,1515 @@ protected void DeserializePropertiesFromResources(IDesignerSerializationManager
[SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
protected void DeserializeStatement(IDesignerSerializationManager manager, CodeStatement statement)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ using (TraceScope("CodeDomSerializerBase::DeserializeStatement"))
+ {
+ Trace("Statement : {0}", statement.GetType().Name);
+
+ // Push this statement onto the context stack. This allows any serializers handling an expression to know what it was connected to.
+ manager.Context.Push(statement);
+ try
+ {
+ // Perf: is -> as changes, change ordering based on possibility of occurance
+ // Please excuse the bad formatting, but I think it is more readable this way than nested indenting.
+ if (statement is CodeAssignStatement cas)
+ {
+ DeserializeAssignStatement(manager, cas);
+ }
+ else
+ {
+ if (statement is CodeVariableDeclarationStatement cvds)
+ {
+ DeserializeVariableDeclarationStatement(manager, cvds);
+ }
+ else if (statement is CodeCommentStatement)
+ {
+ // do nothing for comments. This just supresses the debug warning
+ }
+ else
+ {
+ CodeExpressionStatement ces = statement as CodeExpressionStatement;
+ if (ces != null)
+ {
+ DeserializeExpression(manager, null, ces.Expression);
+ }
+ else
+ {
+ if (statement is CodeMethodReturnStatement cmrs)
+ {
+ DeserializeExpression(manager, null, ces.Expression);
+ }
+ else
+ {
+ if (statement is CodeAttachEventStatement caes)
+ {
+ DeserializeAttachEventStatement(manager, caes);
+ }
+ else
+ {
+ if (statement is CodeRemoveEventStatement cres)
+ {
+ DeserializeDetachEventStatement(manager, cres);
+ }
+ else
+ {
+ if (statement is CodeLabeledStatement cls)
+ {
+ DeserializeStatement(manager, cls.Statement);
+ }
+ else
+ {
+ TraceWarning("Unrecognized statement type: {0}", statement.GetType().Name);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (CheckoutException)
+ {
+ throw; // we want to propagate those all the way up
+ }
+ catch (Exception e)
+ {
+ // Since we always go through reflection, don't show what our engine does, show what caused the problem.
+ if (e is TargetInvocationException)
+ {
+ e = e.InnerException;
+ }
+
+ if (!(e is CodeDomSerializerException) && statement.LinePragma != null)
+ {
+ e = new CodeDomSerializerException(e, statement.LinePragma);
+ }
+
+ manager.ReportError(e);
+ }
+ finally
+ {
+ Debug.Assert(manager.Context.Current == statement, "Someone corrupted the context stack");
+ manager.Context.Pop();
+ }
+ }
+ }
+
+ private void DeserializeVariableDeclarationStatement(IDesignerSerializationManager manager, CodeVariableDeclarationStatement statement)
+ {
+ using (TraceScope("CodeDomSerializerBase::DeserializeVariableDeclarationStatement"))
+ {
+ if (statement.InitExpression != null)
+ {
+ Trace("Processing init expression");
+ DeserializeExpression(manager, statement.Name, statement.InitExpression);
+ }
+ }
+ }
+
+ private void DeserializeDetachEventStatement(IDesignerSerializationManager manager, CodeRemoveEventStatement statement)
+ {
+ using (TraceScope("CodeDomSerializerBase::DeserializeDetachEventStatement"))
+ {
+ object eventListener = DeserializeExpression(manager, null, statement.Listener);
+ TraceErrorIf(!(eventListener is CodeDelegateCreateExpression), "Unable to simplify event attach RHS to a delegate create.");
+ if (eventListener is CodeDelegateCreateExpression delegateCreate)
+ {
+ // We only support binding methods to the root object.
+ object eventAttachObject = DeserializeExpression(manager, null, delegateCreate.TargetObject);
+ RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)];
+ bool isRoot = rootExp == null || (rootExp != null && rootExp.Value == eventAttachObject);
+ TraceWarningIf(!isRoot, "Event is bound to an object other than the root. We do not support this.");
+ if (isRoot)
+ {
+ // Now deserialize the LHS of the event attach to discover the guy whose event we are attaching.
+ object targetObject = DeserializeExpression(manager, null, statement.Event.TargetObject);
+ TraceErrorIf(targetObject is CodeExpression, "Unable to simplify event attach LHS to an object reference.");
+ if (!(targetObject is CodeExpression))
+ {
+ EventDescriptor evt = GetEventsHelper(manager, targetObject, null)[statement.Event.EventName];
+ if (evt != null)
+ {
+ IEventBindingService evtSvc = (IEventBindingService)manager.GetService(typeof(IEventBindingService));
+ if (evtSvc != null)
+ {
+ PropertyDescriptor prop = evtSvc.GetEventProperty(evt);
+ prop.SetValue(targetObject, null);
+ }
+ }
+ else
+ {
+ TraceError("Object {0} does not have a event {1}", targetObject.GetType().Name, statement.Event.EventName);
+ Error(manager, string.Format(SR.SerializerNoSuchEvent, targetObject.GetType().FullName, statement.Event.EventName), SR.SerializerNoSuchEvent);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void DeserializeAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement statement)
+ {
+ using (TraceScope("CodeDomSerializerBase::DeserializeAssignStatement"))
+ {
+ // Since we're doing an assignment into something, we need to know what that something is. It can be a property, a variable, or a member. Anything else is invalid.
+ //Perf: is -> as changes, change ordering based on possibility of occurence
+ CodeExpression expression = statement.Left;
+ CodePropertyReferenceExpression propertyReferenceEx;
+ CodeFieldReferenceExpression fieldReferenceEx;
+ CodeVariableReferenceExpression variableReferenceEx;
+ CodeArrayIndexerExpression arrayIndexerEx;
+
+ Trace("Processing LHS");
+ if ((propertyReferenceEx = expression as CodePropertyReferenceExpression) != null)
+ {
+ DeserializePropertyAssignStatement(manager, statement, propertyReferenceEx, true);
+ }
+ else if ((fieldReferenceEx = expression as CodeFieldReferenceExpression) != null)
+ {
+ Trace("LHS is field : {0}", fieldReferenceEx.FieldName);
+ object lhs = DeserializeExpression(manager, fieldReferenceEx.FieldName, fieldReferenceEx.TargetObject);
+ if (lhs != null)
+ {
+ RootContext root = (RootContext)manager.Context[typeof(RootContext)];
+
+ if (root != null && root.Value == lhs)
+ {
+ Trace("Processing RHS");
+ object rhs = DeserializeExpression(manager, fieldReferenceEx.FieldName, statement.Right);
+ if (rhs is CodeExpression)
+ {
+ TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name);
+ return;
+ }
+ }
+ else
+ {
+ FieldInfo f;
+ object instance;
+ Type type = lhs as Type;
+
+ if (type != null)
+ {
+ instance = null;
+ f = GetReflectionTypeFromTypeHelper(manager, type).GetField(fieldReferenceEx.FieldName, BindingFlags.GetField | BindingFlags.Static | BindingFlags.Public);
+ }
+ else
+ {
+ instance = lhs;
+ f = GetReflectionTypeHelper(manager, lhs).GetField(fieldReferenceEx.FieldName, BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Public);
+ }
+
+ if (f != null)
+ {
+ Trace("Processing RHS");
+ object rhs = DeserializeExpression(manager, fieldReferenceEx.FieldName, statement.Right);
+ if (rhs is CodeExpression)
+ {
+ TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name);
+ return;
+ }
+
+ if (rhs is IConvertible ic)
+ {
+ // f.FieldType is a type from the reflection (or project target) Universe, while rhs is a runtime type(exists in the visual studio framework) they need to be converted to the same universe for comparison to work. If TargetFrameworkProvider is not available, then we are working with runtime types.
+ Type fieldType = f.FieldType;
+ TypeDescriptionProvider tdp = GetTargetFrameworkProviderForType(manager, fieldType);
+ if (tdp != null)
+ {
+ fieldType = tdp.GetRuntimeType(fieldType);
+ }
+ if (fieldType != rhs.GetType())
+ {
+ try
+ {
+ rhs = ic.ToType(fieldType, null);
+ }
+ catch
+ {
+ // oh well...
+ }
+ }
+ }
+
+ f.SetValue(instance, rhs);
+ }
+ else
+ {
+ //lets try it as a property:
+ CodePropertyReferenceExpression propRef = new CodePropertyReferenceExpression();
+ propRef.TargetObject = fieldReferenceEx.TargetObject;
+ propRef.PropertyName = fieldReferenceEx.FieldName;
+ if (!DeserializePropertyAssignStatement(manager, statement, propRef, false))
+ {
+ TraceError("Object {0} does not have a field {1}", lhs.GetType().Name, fieldReferenceEx.FieldName);
+ Error(manager, string.Format(SR.SerializerNoSuchField, lhs.GetType().FullName, fieldReferenceEx.FieldName), SR.SerializerNoSuchField);
+ }
+ }
+ }
+ }
+ else
+ {
+ TraceWarning("Could not find target object for field {0}", fieldReferenceEx.FieldName);
+ }
+ }
+ else if ((variableReferenceEx = expression as CodeVariableReferenceExpression) != null)
+ {
+ // This is the easiest. Just relate the RHS object to the name of the variable.
+ Trace("Processing RHS");
+ object rhs = DeserializeExpression(manager, variableReferenceEx.VariableName, statement.Right);
+ if (rhs is CodeExpression)
+ {
+ TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name);
+ return;
+ }
+ manager.SetName(rhs, variableReferenceEx.VariableName);
+ }
+ else if ((arrayIndexerEx = expression as CodeArrayIndexerExpression) != null)
+ {
+ int[] indexes = new int[arrayIndexerEx.Indices.Count];
+ Trace("LHS is Array Indexer with dims {0}", indexes.Length);
+ object array = DeserializeExpression(manager, null, arrayIndexerEx.TargetObject);
+ bool indexesOK = true;
+
+ // The indexes have to be of type int32. If they're not, then we cannot assign to this array.
+ for (int i = 0; i < indexes.Length; i++)
+ {
+ object index = DeserializeExpression(manager, null, arrayIndexerEx.Indices[i]);
+ if (index is IConvertible ic)
+ {
+ indexes[i] = ic.ToInt32(null);
+ Trace("[{0}] == {1}", i, indexes[i]);
+ }
+ else
+ {
+ TraceWarning("Index {0} could not be converted to int. Type: {1}", i, (index == null ? "(null)" : index.GetType().Name));
+ indexesOK = false;
+ break;
+ }
+ }
+
+ if (array is Array arr && indexesOK)
+ {
+ Trace("Processing RHS");
+ object rhs = DeserializeExpression(manager, null, statement.Right);
+ if (rhs is CodeExpression)
+ {
+ TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name);
+ return;
+ }
+ arr.SetValue(rhs, indexes);
+ }
+ else
+ {
+ TraceErrorIf(!(array is Array), "Array resovled to something other than an array: {0}", (array == null ? "(null)" : array.GetType().Name));
+ TraceErrorIf(!indexesOK, "Indexes to array could not be converted to int32.");
+ }
+ }
+ }
+ }
+
+ [Conditional("DEBUG")]
+ internal static void TraceError(string message, params object[] values)
+ {
+ if (traceSerialization.TraceError)
+ {
+ string scope = string.Empty;
+ if (traceScope != null)
+ {
+ foreach (string scopeName in traceScope)
+ {
+ if (scope.Length > 0)
+ {
+ scope = "/" + scope;
+ }
+ scope = scopeName + scope;
+ }
+ }
+
+ Debug.WriteLine("***************************************************");
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "*** ERROR :{0}", string.Format(CultureInfo.CurrentCulture, message, values)));
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "*** SCOPE :{0}", scope));
+ Debug.WriteLine("***************************************************");
+ }
+ }
+
+ ///
+ /// This is a helper method that will deserialize a given expression. It deserializes
+ /// the statement by interpreting and executing the CodeDom expression, returning
+ /// the results.
+ ///
+ [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
+ [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
+ protected object DeserializeExpression(IDesignerSerializationManager manager, string name, CodeExpression expression)
+ {
+ object result = expression;
+ using (TraceScope("CodeDomSerializerBase::DeserializeExpression"))
+ {
+ // Perf: is -> as changes, change ordering based on possibility of occurance
+ // If you are adding to this, use as instead of is + cast and order new expressions in order of frequency in typical user code.
+ CodePrimitiveExpression primitiveEx;
+ CodePropertyReferenceExpression propertyReferenceEx;
+ CodeTypeReferenceExpression typeReferenceEx;
+ CodeObjectCreateExpression objectCreateEx;
+ CodeArgumentReferenceExpression argumentReferenceEx;
+ CodeFieldReferenceExpression fieldReferenceEx;
+ CodeMethodInvokeExpression methodInvokeEx;
+ CodeVariableReferenceExpression variableReferenceEx;
+ CodeCastExpression castEx;
+ CodeArrayCreateExpression arrayCreateEx;
+ CodeArrayIndexerExpression arrayIndexerEx;
+ CodeBinaryOperatorExpression binaryOperatorEx;
+ CodeDelegateInvokeExpression delegateInvokeEx;
+ CodeDirectionExpression directionEx;
+ CodeIndexerExpression indexerEx;
+ CodeParameterDeclarationExpression parameterDeclaration;
+ CodeTypeOfExpression typeOfExpression;
+
+ while (result != null)
+ {
+ if ((primitiveEx = result as CodePrimitiveExpression) != null)
+ {
+ Trace("Primitive. Value: {0}", (primitiveEx.Value == null ? "(null)" : primitiveEx.Value));
+ result = primitiveEx.Value;
+ break;
+ }
+ else if ((propertyReferenceEx = result as CodePropertyReferenceExpression) != null)
+ {
+ result = DeserializePropertyReferenceExpression(manager, propertyReferenceEx, true);
+ break;
+ }
+ else if (result is CodeThisReferenceExpression)
+ { //(is -> as doesn't help here, since the cast is different)
+ Trace("'this' reference");
+ RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)];
+ if (rootExp != null)
+ {
+ result = rootExp.Value;
+ }
+ else
+ {
+ // Last ditch effort. Some things have to code gen against "this", such as event wireups. Those are always bounda against the root component.
+ if (manager.GetService(typeof(IDesignerHost)) is IDesignerHost host)
+ {
+ result = host.RootComponent;
+ }
+ }
+
+ if (result == null)
+ {
+ TraceError("CodeThisReferenceExpression not handled because there is no root context or the root context did not contain an instance.");
+ Error(manager, string.Format(SR.SerializerNoRootExpression), SR.SerializerNoRootExpression);
+ }
+
+ break;
+ }
+ else if ((typeReferenceEx = result as CodeTypeReferenceExpression) != null)
+ {
+ Trace("TypeReference : {0}", typeReferenceEx.Type.BaseType);
+ result = manager.GetType(GetTypeNameFromCodeTypeReference(manager, typeReferenceEx.Type));
+ break;
+ }
+ else if ((objectCreateEx = result as CodeObjectCreateExpression) != null)
+ {
+ Trace("Object create");
+ result = null;
+ Type type = manager.GetType(GetTypeNameFromCodeTypeReference(manager, objectCreateEx.CreateType));
+ if (type != null)
+ {
+ object[] parameters = new object[objectCreateEx.Parameters.Count];
+ bool paramsOk = true;
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = DeserializeExpression(manager, null, objectCreateEx.Parameters[i]);
+ if (parameters[i] is CodeExpression)
+ {
+ // Before we bail on this parameter, see if the type is a delegate. If we are creating a delegate we may be able to bind to the method after all.
+ if (typeof(Delegate).IsAssignableFrom(type) && parameters.Length == 1 && parameters[i] is CodeMethodReferenceExpression)
+ {
+ CodeMethodReferenceExpression methodRef = (CodeMethodReferenceExpression)parameters[i];
+
+ // Only do this if our target is not the root context.
+ if (!(methodRef.TargetObject is CodeThisReferenceExpression))
+ {
+ object target = DeserializeExpression(manager, null, methodRef.TargetObject);
+ if (!(target is CodeExpression))
+ {
+ // Search for a matching method sig. Must be public since we don't own this object
+ MethodInfo delegateInvoke = type.GetMethod("Invoke");
+ if (delegateInvoke != null)
+ {
+ ParameterInfo[] delegateParams = delegateInvoke.GetParameters();
+ Type[] paramTypes = new Type[delegateParams.Length];
+ for (int idx = 0; idx < paramTypes.Length; idx++)
+ {
+ paramTypes[idx] = delegateParams[i].ParameterType;
+ }
+ MethodInfo mi = GetReflectionTypeHelper(manager, target).GetMethod(methodRef.MethodName, paramTypes);
+ if (mi != null)
+ {
+ // MethodInfo from the reflection Universe might not implement MethodHandle property, once we know that the method is available, get it from the runtime type.
+ mi = target.GetType().GetMethod(methodRef.MethodName, paramTypes);
+ result = Activator.CreateInstance(type, new object[] { target, mi.MethodHandle.GetFunctionPointer() });
+ }
+ }
+ }
+ }
+ }
+ // Technically, the paramters are not OK. Our special case above, if successful, would have produced a "result" object for us.
+ paramsOk = false;
+ break;
+ }
+ }
+
+ if (paramsOk)
+ {
+ // Create an instance of the object. If the caller provided a name, then ask the manager to add this object to the container.
+ result = DeserializeInstance(manager, type, parameters, name, (name != null));
+ }
+ }
+ else
+ {
+ TraceError("Type {0} could not be loaded", objectCreateEx.CreateType.BaseType);
+ Error(manager, string.Format(SR.SerializerTypeNotFound, objectCreateEx.CreateType.BaseType), SR.SerializerTypeNotFound);
+ }
+ break;
+ }
+ else if ((argumentReferenceEx = result as CodeArgumentReferenceExpression) != null)
+ {
+ Trace("Named argument reference : {0}", argumentReferenceEx.ParameterName);
+ result = manager.GetInstance(argumentReferenceEx.ParameterName);
+ if (result == null)
+ {
+ TraceError("Parameter {0} does not exist", argumentReferenceEx.ParameterName);
+ Error(manager, string.Format(SR.SerializerUndeclaredName, argumentReferenceEx.ParameterName), SR.SerializerUndeclaredName);
+ }
+ break;
+ }
+ else if ((fieldReferenceEx = result as CodeFieldReferenceExpression) != null)
+ {
+ Trace("Field reference : {0}", fieldReferenceEx.FieldName);
+ object target = DeserializeExpression(manager, null, fieldReferenceEx.TargetObject);
+ if (target != null && !(target is CodeExpression))
+ {
+ // If the target is the root object, then this won't be found through reflection. Instead, ask the manager for the field by name.
+ RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)];
+ if (rootExp != null && rootExp.Value == target)
+ {
+ object namedObject = manager.GetInstance(fieldReferenceEx.FieldName);
+ if (namedObject != null)
+ {
+ result = namedObject;
+ }
+ else
+ {
+ TraceError("Field {0} could not be resolved", fieldReferenceEx.FieldName);
+ Error(manager, string.Format(SR.SerializerUndeclaredName, fieldReferenceEx.FieldName), SR.SerializerUndeclaredName);
+ }
+ }
+ else
+ {
+ FieldInfo field;
+ object instance;
+ Type t = target as Type;
+ if (t != null)
+ {
+ instance = null;
+ field = GetReflectionTypeFromTypeHelper(manager, t).GetField(fieldReferenceEx.FieldName, BindingFlags.GetField | BindingFlags.Static | BindingFlags.Public);
+ }
+ else
+ {
+ instance = target;
+ field = GetReflectionTypeHelper(manager, target).GetField(fieldReferenceEx.FieldName, BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Public);
+ }
+
+ if (field != null)
+ {
+ result = field.GetValue(instance);
+ }
+ else
+ {
+ //lets try it as a property:
+ CodePropertyReferenceExpression propRef = new CodePropertyReferenceExpression();
+ propRef.TargetObject = fieldReferenceEx.TargetObject;
+ propRef.PropertyName = fieldReferenceEx.FieldName;
+
+ result = DeserializePropertyReferenceExpression(manager, propRef, false);
+ if (result == fieldReferenceEx)
+ {
+ Error(manager, string.Format(SR.SerializerUndeclaredName, fieldReferenceEx.FieldName), SR.SerializerUndeclaredName);
+ }
+ }
+ }
+ }
+ else
+ {
+ Error(manager, string.Format(SR.SerializerFieldTargetEvalFailed, fieldReferenceEx.FieldName), SR.SerializerFieldTargetEvalFailed);
+ }
+
+ TraceWarningIf(result == fieldReferenceEx, "Could not resolve field {0} to an object instance.", fieldReferenceEx.FieldName);
+ break;
+ }
+ else if ((methodInvokeEx = result as CodeMethodInvokeExpression) != null)
+ {
+ Trace("Method invoke : {0}", methodInvokeEx.Method.MethodName);
+
+ object targetObject = DeserializeExpression(manager, null, methodInvokeEx.Method.TargetObject);
+
+ if (targetObject != null)
+ {
+ object[] parameters = new object[methodInvokeEx.Parameters.Count];
+ bool paramsOk = true;
+
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = DeserializeExpression(manager, null, methodInvokeEx.Parameters[i]);
+ if (parameters[i] is CodeExpression)
+ {
+ paramsOk = false;
+ break;
+ }
+ }
+
+ if (paramsOk)
+ {
+ IComponentChangeService compChange = (IComponentChangeService)manager.GetService(typeof(IComponentChangeService));
+ Type t = targetObject as Type;
+
+ if (t != null)
+ {
+ result = GetReflectionTypeFromTypeHelper(manager, t).InvokeMember(methodInvokeEx.Method.MethodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, parameters, null, null, null);
+ }
+ else
+ {
+ if (compChange != null)
+ {
+ compChange.OnComponentChanging(targetObject, null);
+ }
+
+ try
+ {
+ result = GetReflectionTypeHelper(manager, targetObject).InvokeMember(methodInvokeEx.Method.MethodName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, targetObject, parameters, null, null, null);
+ }
+ catch (MissingMethodException)
+ {
+ // We did not find the method directly. Let's see if we can find it
+ // as an private implemented interface name.
+ //
+ CodeCastExpression castExpr = methodInvokeEx.Method.TargetObject as CodeCastExpression;
+
+ if (castExpr != null)
+ {
+ Type castType = manager.GetType(GetTypeNameFromCodeTypeReference(manager, castExpr.TargetType));
+
+ if (castType != null && castType.IsInterface)
+ {
+ result = GetReflectionTypeFromTypeHelper(manager, castType).InvokeMember(methodInvokeEx.Method.MethodName, BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, targetObject, parameters, null, null, null);
+ }
+ else
+ {
+ throw;
+ }
+ }
+ else
+ {
+ throw;
+ }
+ }
+ if (compChange != null)
+ {
+ compChange.OnComponentChanged(targetObject, null, null, null);
+ }
+ }
+ }
+ else if (parameters.Length == 1 && parameters[0] is CodeDelegateCreateExpression)
+ {
+ string methodName = methodInvokeEx.Method.MethodName;
+
+ if (methodName.StartsWith("add_"))
+ {
+ methodName = methodName.Substring(4);
+ DeserializeAttachEventStatement(manager, new CodeAttachEventStatement(methodInvokeEx.Method.TargetObject, methodName, (CodeExpression)parameters[0]));
+ result = null;
+ }
+ }
+ }
+
+ break;
+ }
+ else if ((variableReferenceEx = result as CodeVariableReferenceExpression) != null)
+ {
+ Trace("Variable reference : {0}", variableReferenceEx.VariableName);
+ result = manager.GetInstance(variableReferenceEx.VariableName);
+ if (result == null)
+ {
+ TraceError("Variable {0} does not exist", variableReferenceEx.VariableName);
+ Error(manager, string.Format(SR.SerializerUndeclaredName, variableReferenceEx.VariableName), SR.SerializerUndeclaredName);
+ }
+
+ break;
+ }
+ else if ((castEx = result as CodeCastExpression) != null)
+ {
+ Trace("Cast : {0}", castEx.TargetType.BaseType);
+ result = DeserializeExpression(manager, name, castEx.Expression);
+ if (result is IConvertible ic)
+ {
+ Type targetType = manager.GetType(GetTypeNameFromCodeTypeReference(manager, castEx.TargetType));
+ if (targetType != null)
+ {
+ result = ic.ToType(targetType, null);
+ }
+ }
+ break;
+ }
+ else if (result is CodeBaseReferenceExpression)
+ { //(is -> as doesn't help here, since the cast is different)
+ RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)];
+ if (rootExp != null)
+ {
+ result = rootExp.Value;
+ }
+ else
+ {
+ result = null;
+ }
+ break;
+ }
+ else if ((arrayCreateEx = result as CodeArrayCreateExpression) != null)
+ {
+ Trace("Array create : {0}", arrayCreateEx.CreateType.BaseType);
+ Type arrayType = manager.GetType(GetTypeNameFromCodeTypeReference(manager, arrayCreateEx.CreateType));
+ Array array = null;
+
+ if (arrayType != null)
+ {
+ if (arrayCreateEx.Initializers.Count > 0)
+ {
+ Trace("{0} initializers", arrayCreateEx.Initializers.Count);
+ // Passed an array of initializers. Use this to create the array. Note that we use an ArrayList here and add elements as we create them. It is possible that an element cannot be resolved. This is an error, but we do not want to tank the entire array. If we kicked out the entire statement, a missing control would cause all controls on a form to vanish.
+ ArrayList arrayList = new ArrayList(arrayCreateEx.Initializers.Count);
+
+ foreach (CodeExpression initializer in arrayCreateEx.Initializers)
+ {
+ try
+ {
+ object o = DeserializeExpression(manager, null, initializer);
+
+ if (!(o is CodeExpression))
+ {
+ if (!arrayType.IsInstanceOfType(o))
+ {
+ o = Convert.ChangeType(o, arrayType, CultureInfo.InvariantCulture);
+ }
+
+ arrayList.Add(o);
+ }
+ }
+ catch (Exception ex)
+ {
+ manager.ReportError(ex);
+ }
+ }
+
+ array = Array.CreateInstance(arrayType, arrayList.Count);
+ arrayList.CopyTo(array, 0);
+ }
+ else if (arrayCreateEx.SizeExpression != null)
+ {
+ object o = DeserializeExpression(manager, name, arrayCreateEx.SizeExpression);
+ Debug.Assert(o is IConvertible, "Array size expression could not be resolved to IConvertible: " + (o == null ? "(null)" : o.GetType().Name));
+ IConvertible ic = o as IConvertible;
+
+ if (ic != null)
+ {
+ int size = ic.ToInt32(null);
+ Trace("Initialized with expression that simplified to {0}", size);
+ array = Array.CreateInstance(arrayType, size);
+ }
+ }
+ else
+ {
+ Trace("Initialized with size {0}", arrayCreateEx.Size);
+ array = Array.CreateInstance(arrayType, arrayCreateEx.Size);
+ }
+ }
+ else
+ {
+ TraceError("Type could not be resolved: {0}", arrayCreateEx.CreateType.BaseType);
+ Error(manager, string.Format(SR.SerializerTypeNotFound, arrayCreateEx.CreateType.BaseType), SR.SerializerTypeNotFound);
+ }
+
+ result = array;
+ if (result != null && name != null)
+ {
+ manager.SetName(result, name);
+ }
+
+ break;
+ }
+ else if ((arrayIndexerEx = result as CodeArrayIndexerExpression) != null)
+ {
+ Trace("Array indexer");
+
+ // For this, assume in any error we return a null. The only errors
+ // here should come from a mal-formed expression.
+ //
+ result = null;
+
+ Array array = DeserializeExpression(manager, name, arrayIndexerEx.TargetObject) as Array;
+
+ if (array != null)
+ {
+ int[] indexes = new int[arrayIndexerEx.Indices.Count];
+
+ Trace("Dims: {0}", indexes.Length);
+
+ bool indexesOK = true;
+
+ // The indexes have to be of type int32. If they're not, then
+ // we cannot assign to this array.
+ //
+ for (int i = 0; i < indexes.Length; i++)
+ {
+ IConvertible index = DeserializeExpression(manager, name, arrayIndexerEx.Indices[i]) as IConvertible;
+
+ if (index != null)
+ {
+ indexes[i] = index.ToInt32(null);
+ Trace("[{0}] == {1}", i, indexes[i]);
+ }
+ else
+ {
+ TraceWarning("Index {0} could not be converted to int. Type: {1}", i, (index == null ? "(null)" : index.GetType().Name));
+ indexesOK = false;
+ break;
+ }
+ }
+
+ if (indexesOK)
+ {
+ result = array.GetValue(indexes);
+ }
+ }
+
+ break;
+ }
+ else if ((binaryOperatorEx = result as CodeBinaryOperatorExpression) != null)
+ {
+ Trace("Binary operator : {0}", binaryOperatorEx.Operator);
+
+ object left = DeserializeExpression(manager, null, binaryOperatorEx.Left);
+ object right = DeserializeExpression(manager, null, binaryOperatorEx.Right);
+
+ // We assign the result to an arbitrary value here in case the operation could
+ // not be performed.
+ //
+ result = left;
+
+ IConvertible icLeft = left as IConvertible;
+ IConvertible icRight = right as IConvertible;
+
+ if (icLeft != null && icRight != null)
+ {
+ result = ExecuteBinaryExpression(icLeft, icRight, binaryOperatorEx.Operator);
+ }
+ else
+ {
+ TraceWarning("Could not simplify left and right binary operators to IConvertible.");
+ }
+ break;
+ }
+ else if ((delegateInvokeEx = result as CodeDelegateInvokeExpression) != null)
+ {
+ Trace("Delegate invoke");
+ object targetObject = DeserializeExpression(manager, null, delegateInvokeEx.TargetObject);
+ if (targetObject is Delegate del)
+ {
+ object[] parameters = new object[delegateInvokeEx.Parameters.Count];
+ bool paramsOk = true;
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameters[i] = DeserializeExpression(manager, null, delegateInvokeEx.Parameters[i]);
+ if (parameters[i] is CodeExpression)
+ {
+ paramsOk = false;
+ break;
+ }
+ }
+
+ if (paramsOk)
+ {
+ Trace("Invoking {0} with {1} parameters", targetObject.GetType().Name, parameters.Length);
+ del.DynamicInvoke(parameters);
+ }
+ }
+
+ break;
+ }
+ else if ((directionEx = result as CodeDirectionExpression) != null)
+ {
+ Trace("Direction operator");
+ result = DeserializeExpression(manager, name, directionEx.Expression);
+ break;
+ }
+ else if ((indexerEx = result as CodeIndexerExpression) != null)
+ {
+ Trace("Indexer");
+ // For this, assume in any error we return a null. The only errors here should come from a mal-formed expression.
+ result = null;
+ object targetObject = DeserializeExpression(manager, null, indexerEx.TargetObject);
+ if (targetObject != null)
+ {
+ object[] indexes = new object[indexerEx.Indices.Count];
+ Trace("Indexes: {0}", indexes.Length);
+ bool indexesOK = true;
+ for (int i = 0; i < indexes.Length; i++)
+ {
+ indexes[i] = DeserializeExpression(manager, null, indexerEx.Indices[i]);
+ if (indexes[i] is CodeExpression)
+ {
+ TraceWarning("Index {0} could not be simplified to an object.", i);
+ indexesOK = false;
+ break;
+ }
+ }
+
+ if (indexesOK)
+ {
+ result = GetReflectionTypeHelper(manager, targetObject).InvokeMember("Item", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, targetObject, indexes, null, null, null);
+ }
+ }
+ break;
+ }
+ else if (result is CodeSnippetExpression)
+ {
+ Trace("Snippet");
+ result = null;
+ break;
+ }
+ else if ((parameterDeclaration = result as CodeParameterDeclarationExpression) != null)
+ {
+ Trace("Parameter declaration");
+ result = manager.GetType(GetTypeNameFromCodeTypeReference(manager, parameterDeclaration.Type));
+ break;
+ }
+ else if ((typeOfExpression = result as CodeTypeOfExpression) != null)
+ {
+ Trace("Typeof({0})", typeOfExpression.Type.BaseType);
+ string type = GetTypeNameFromCodeTypeReference(manager, typeOfExpression.Type);
+ // add the array ranks so we get the right type of this thing.
+ for (int i = 0; i < typeOfExpression.Type.ArrayRank; i++)
+ {
+ type += "[]";
+ }
+
+ result = manager.GetType(type);
+ if (result == null)
+ {
+ TraceError("Type could not be resolved: {0}", type);
+ Error(manager, string.Format(SR.SerializerTypeNotFound, type), SR.SerializerTypeNotFound);
+ }
+ break;
+ }
+ else if (result is CodeEventReferenceExpression || result is CodeMethodReferenceExpression || result is CodeDelegateCreateExpression)
+ {
+ // These are all the expressions we know about, but expect to return to the caller because we cannot simplify them.
+ break;
+ }
+ else
+ {
+ // All expression evaluation happens above. This codepath indicates that we got some sort of junk in the evalualtor, or that someone assigned result to a value without breaking out of the loop.
+ Debug.Fail("Unrecognized expression type: " + result.GetType().Name);
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ private void DeserializeAttachEventStatement(IDesignerSerializationManager manager, CodeAttachEventStatement statement)
+ {
+ using (TraceScope("CodeDomSerializerBase::DeserializeAttachEventStatement"))
+ {
+ string handlerMethodName = null;
+ object eventAttachObject = null;
+
+ // Get the target information
+ object targetObject = DeserializeExpression(manager, null, statement.Event.TargetObject);
+ string eventName = statement.Event.EventName;
+ Debug.Assert(targetObject != null, "Failed to get target object for event attach");
+ Debug.Assert(eventName != null, "Failed to get eventName for event attach");
+ if (eventName == null || targetObject == null)
+ {
+ return;
+ }
+
+ if (statement.Listener is CodeObjectCreateExpression objCreate)
+ {
+ // now walk into the CodeObjectCreateExpression and get the parameters so we can get the name of the method, e.g. button1_Click
+ if (objCreate.Parameters.Count == 1)
+ {
+ // if this is a delegate create (new EventHandler(this.button1_Click)), then the first parameter should be a method ref.
+ if (objCreate.Parameters[0] is CodeMethodReferenceExpression methodRef)
+ {
+ handlerMethodName = methodRef.MethodName;
+ eventAttachObject = DeserializeExpression(manager, null, methodRef.TargetObject);
+ }
+ }
+ else
+ {
+ Debug.Fail("Encountered delegate object create with more or less than 1 parameter?");
+ }
+ }
+ else
+ {
+ object eventListener = DeserializeExpression(manager, null, statement.Listener);
+ if (eventListener is CodeDelegateCreateExpression delegateCreate)
+ {
+ eventAttachObject = DeserializeExpression(manager, null, delegateCreate.TargetObject);
+ handlerMethodName = delegateCreate.MethodName;
+ }
+ }
+
+ RootContext rootExp = (RootContext)manager.Context[typeof(RootContext)];
+ bool isRoot = rootExp == null || (rootExp != null && rootExp.Value == eventAttachObject);
+
+ if (handlerMethodName == null)
+ {
+ TraceError("Unable to retrieve handler method and object for delegate create.");
+ }
+ else
+ {
+ // We only support binding methods to the root object.
+ //
+ TraceWarningIf(!isRoot, "Event is bound to an object other than the root. We do not support this.");
+ if (isRoot)
+ {
+ // Now deserialize the LHS of the event attach to discover the guy whose
+ // event we are attaching.
+ //
+ TraceErrorIf(targetObject is CodeExpression, "Unable to simplify event attach LHS to an object reference.");
+ if (!(targetObject is CodeExpression))
+ {
+ EventDescriptor evt = GetEventsHelper(manager, targetObject, null)[eventName];
+
+ if (evt != null)
+ {
+ IEventBindingService evtSvc = (IEventBindingService)manager.GetService(typeof(IEventBindingService));
+
+ if (evtSvc != null)
+ {
+ PropertyDescriptor prop = evtSvc.GetEventProperty(evt);
+
+ prop.SetValue(targetObject, handlerMethodName);
+ Trace("Attached event {0}.{1} to {2}", targetObject.GetType().Name, eventName, handlerMethodName);
+ }
+ }
+ else
+ {
+ TraceError("Object {0} does not have a event {1}", targetObject.GetType().Name, eventName);
+ Error(manager, string.Format(SR.SerializerNoSuchEvent, targetObject.GetType().FullName, eventName), SR.SerializerNoSuchEvent);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private object ExecuteBinaryExpression(IConvertible left, IConvertible right, CodeBinaryOperatorType op)
+ {
+
+ // "Binary" operator type is actually a combination of several types of operators: boolean, binary and math. Group them into categories here.
+ CodeBinaryOperatorType[] booleanOperators = new CodeBinaryOperatorType[] {
+ CodeBinaryOperatorType.IdentityInequality,
+ CodeBinaryOperatorType.IdentityEquality,
+ CodeBinaryOperatorType.ValueEquality,
+ CodeBinaryOperatorType.BooleanOr,
+ CodeBinaryOperatorType.BooleanAnd,
+ CodeBinaryOperatorType.LessThan,
+ CodeBinaryOperatorType.LessThanOrEqual,
+ CodeBinaryOperatorType.GreaterThan,
+ CodeBinaryOperatorType.GreaterThanOrEqual
+ };
+
+ CodeBinaryOperatorType[] mathOperators = new CodeBinaryOperatorType[] {
+ CodeBinaryOperatorType.Add,
+ CodeBinaryOperatorType.Subtract,
+ CodeBinaryOperatorType.Multiply,
+ CodeBinaryOperatorType.Divide,
+ CodeBinaryOperatorType.Modulus
+ };
+
+ CodeBinaryOperatorType[] binaryOperators = new CodeBinaryOperatorType[] {
+ CodeBinaryOperatorType.BitwiseOr,
+ CodeBinaryOperatorType.BitwiseAnd
+ };
+
+ // Figure out what kind of expression we have.
+ for (int i = 0; i < binaryOperators.Length; i++)
+ {
+ if (op == binaryOperators[i])
+ {
+ return ExecuteBinaryOperator(left, right, op);
+ }
+ }
+ for (int i = 0; i < mathOperators.Length; i++)
+ {
+ if (op == mathOperators[i])
+ {
+ return ExecuteMathOperator(left, right, op);
+ }
+ }
+ for (int i = 0; i < booleanOperators.Length; i++)
+ {
+ if (op == booleanOperators[i])
+ {
+ return ExecuteBooleanOperator(left, right, op);
+ }
+ }
+ Debug.Fail("Unsupported binary operator type: " + op.ToString());
+ return left;
+ }
+ private object ExecuteBinaryOperator(IConvertible left, IConvertible right, CodeBinaryOperatorType op)
+ {
+ TypeCode leftType = left.GetTypeCode();
+ TypeCode rightType = right.GetTypeCode();
+
+ // The compatible types are listed in order from lowest bitness to highest. We must operate on the highest bitness to keep fidelity.
+ TypeCode[] compatibleTypes = new TypeCode[] {
+ TypeCode.Byte,
+ TypeCode.Char,
+ TypeCode.Int16,
+ TypeCode.UInt16,
+ TypeCode.Int32,
+ TypeCode.UInt32,
+ TypeCode.Int64,
+ TypeCode.UInt64};
+
+ int leftTypeIndex = -1;
+ int rightTypeIndex = -1;
+
+ for (int i = 0; i < compatibleTypes.Length; i++)
+ {
+ if (leftType == compatibleTypes[i])
+ {
+ leftTypeIndex = i;
+ }
+ if (rightType == compatibleTypes[i])
+ {
+ rightTypeIndex = i;
+ }
+ if (leftTypeIndex != -1 && rightTypeIndex != -1)
+ {
+ break;
+ }
+ }
+
+ if (leftTypeIndex == -1 || rightTypeIndex == -1)
+ {
+ Debug.Fail("Could not convert left or right side to binary-compatible value.");
+ return left;
+ }
+
+ int maxIndex = Math.Max(leftTypeIndex, rightTypeIndex);
+ object result = left;
+ switch (compatibleTypes[maxIndex])
+ {
+ case TypeCode.Byte:
+ {
+ byte leftValue = left.ToByte(null);
+ byte rightValue = right.ToByte(null);
+ if (op == CodeBinaryOperatorType.BitwiseOr)
+ {
+ result = leftValue | rightValue;
+ }
+ else
+ {
+ result = leftValue & rightValue;
+ }
+ break;
+ }
+ case TypeCode.Char:
+ {
+ char leftValue = left.ToChar(null);
+ char rightValue = right.ToChar(null);
+ if (op == CodeBinaryOperatorType.BitwiseOr)
+ {
+ result = leftValue | rightValue;
+ }
+ else
+ {
+ result = leftValue & rightValue;
+ }
+ break;
+ }
+ case TypeCode.Int16:
+ {
+ short leftValue = left.ToInt16(null);
+ short rightValue = right.ToInt16(null);
+ if (op == CodeBinaryOperatorType.BitwiseOr)
+ {
+ result = (short)((ushort)leftValue | (ushort)rightValue);
+ }
+ else
+ {
+ result = leftValue & rightValue;
+ }
+ break;
+ }
+ case TypeCode.UInt16:
+ {
+ ushort leftValue = left.ToUInt16(null);
+ ushort rightValue = right.ToUInt16(null);
+ if (op == CodeBinaryOperatorType.BitwiseOr)
+ {
+ result = leftValue | rightValue;
+ }
+ else
+ {
+ result = leftValue & rightValue;
+ }
+ break;
+ }
+ case TypeCode.Int32:
+ {
+ int leftValue = left.ToInt32(null);
+ int rightValue = right.ToInt32(null);
+ if (op == CodeBinaryOperatorType.BitwiseOr)
+ {
+ result = leftValue | rightValue;
+ }
+ else
+ {
+ result = leftValue & rightValue;
+ }
+ break;
+ }
+ case TypeCode.UInt32:
+ {
+ uint leftValue = left.ToUInt32(null);
+ uint rightValue = right.ToUInt32(null);
+ if (op == CodeBinaryOperatorType.BitwiseOr)
+ {
+ result = leftValue | rightValue;
+ }
+ else
+ {
+ result = leftValue & rightValue;
+ }
+ break;
+ }
+ case TypeCode.Int64:
+ {
+ long leftValue = left.ToInt64(null);
+ long rightValue = right.ToInt64(null);
+ if (op == CodeBinaryOperatorType.BitwiseOr)
+ {
+ result = leftValue | rightValue;
+ }
+ else
+ {
+ result = leftValue & rightValue;
+ }
+ break;
+ }
+ case TypeCode.UInt64:
+ {
+ ulong leftValue = left.ToUInt64(null);
+ ulong rightValue = right.ToUInt64(null);
+ if (op == CodeBinaryOperatorType.BitwiseOr)
+ {
+ result = leftValue | rightValue;
+ }
+ else
+ {
+ result = leftValue & rightValue;
+ }
+ break;
+ }
+ }
+
+ if (result != left && left is Enum)
+ {
+ // For enums, try to convert back to the original type
+ result = Enum.ToObject(left.GetType(), result);
+ }
+ return result;
+ }
+
+ private object ExecuteBooleanOperator(IConvertible left, IConvertible right, CodeBinaryOperatorType op)
+ {
+ bool result = false;
+ switch (op)
+ {
+ case CodeBinaryOperatorType.IdentityInequality:
+ result = (left != right);
+ break;
+ case CodeBinaryOperatorType.IdentityEquality:
+ result = (left == right);
+ break;
+ case CodeBinaryOperatorType.ValueEquality:
+ result = left.Equals(right);
+ break;
+ case CodeBinaryOperatorType.BooleanOr:
+ result = (left.ToBoolean(null) || right.ToBoolean(null));
+ break;
+ case CodeBinaryOperatorType.BooleanAnd:
+ result = (left.ToBoolean(null) && right.ToBoolean(null));
+ break;
+ case CodeBinaryOperatorType.LessThan:
+ // Not doing these at design time.
+ break;
+ case CodeBinaryOperatorType.LessThanOrEqual:
+ // Not doing these at design time.
+ break;
+ case CodeBinaryOperatorType.GreaterThan:
+ // Not doing these at design time.
+ break;
+ case CodeBinaryOperatorType.GreaterThanOrEqual:
+ // Not doing these at design time.
+ break;
+ default:
+ Debug.Fail("Should never get here!");
+ break;
+ }
+
+ return result;
+ }
+
+ private object ExecuteMathOperator(IConvertible left, IConvertible right, CodeBinaryOperatorType op)
+ {
+ switch (op)
+ {
+ case CodeBinaryOperatorType.Add:
+ string leftString = left as string;
+ string rightString = right as string;
+
+ if (leftString == null && left is Char)
+ {
+ leftString = left.ToString();
+ }
+
+ if (rightString == null && right is Char)
+ {
+ rightString = right.ToString();
+ }
+
+ if (leftString != null && rightString != null)
+ {
+ return leftString + rightString;
+ }
+ else
+ {
+ Debug.Fail("Addition operator not supported for this type");
+ return left;
+ }
+ default:
+ Debug.Fail("Math operators are not supported");
+ return left;
+ }
+ }
+
+ [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
+ private object DeserializePropertyReferenceExpression(IDesignerSerializationManager manager, CodePropertyReferenceExpression propertyReferenceEx, bool reportError)
+ {
+ object result = propertyReferenceEx;
+ Trace("Property reference : {0}", propertyReferenceEx.PropertyName);
+ object target = DeserializeExpression(manager, null, propertyReferenceEx.TargetObject);
+ if (target != null && !(target is CodeExpression))
+ {
+ // if it's a type, then we've got ourselves a static field...
+ if (!(target is Type))
+ {
+ PropertyDescriptor prop = GetPropertiesHelper(manager, target, null)[propertyReferenceEx.PropertyName];
+ if (prop != null)
+ {
+ result = prop.GetValue(target);
+ }
+ else
+ {
+ // This could be a protected property on the base class. Make sure we're actually accessing through the base class, and then get the property directly from reflection.
+ if (GetExpression(manager, target) is CodeThisReferenceExpression)
+ {
+ PropertyInfo propInfo = GetReflectionTypeHelper(manager, target).GetProperty(propertyReferenceEx.PropertyName, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ if (propInfo != null)
+ {
+ result = propInfo.GetValue(target, null);
+ }
+ }
+ }
+ }
+ else
+ {
+ PropertyInfo prop = GetReflectionTypeFromTypeHelper(manager, (Type)target).GetProperty(propertyReferenceEx.PropertyName, BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public);
+ if (prop != null)
+ {
+ result = prop.GetValue(null, null);
+ }
+ }
+
+ if (result == propertyReferenceEx && reportError)
+ {
+ string typeName = (target is Type) ? ((Type)target).FullName : GetReflectionTypeHelper(manager, target).FullName;
+ Error(manager, string.Format(SR.SerializerNoSuchProperty, typeName, propertyReferenceEx.PropertyName), SR.SerializerNoSuchProperty);
+ }
+ }
+ TraceWarningIf(result == propertyReferenceEx, "Could not resolve property {0} to an object instance.", propertyReferenceEx.PropertyName);
+ return result;
+ }
+
+ [Conditional("DEBUG")]
+ internal static void TraceErrorIf(bool condition, string message, params object[] values)
+ {
+ if (condition) TraceError(message, values);
+ }
+
+ [Conditional("DEBUG")]
+ internal static void TraceWarningIf(bool condition, string message, params object[] values)
+ {
+ if (condition) TraceWarning(message, values);
+ }
+
+ [Conditional("DEBUG")]
+ internal static void TraceWarning(string message, params object[] values)
+ {
+ if (traceSerialization.TraceWarning)
+ {
+ string scope = string.Empty;
+ if (traceScope != null)
+ {
+ foreach (string scopeName in traceScope)
+ {
+ if (scope.Length > 0)
+ {
+ scope = "/" + scope;
+ }
+ scope = scopeName + scope;
+ }
+ }
+
+ Debug.WriteLine("***************************************************");
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "*** WARNING :{0}", string.Format(CultureInfo.CurrentCulture, message, values)));
+ Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "*** SCOPE :{0}", scope));
+ Debug.WriteLine("***************************************************");
+ }
+ }
+
+ private bool DeserializePropertyAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement statement,
+ CodePropertyReferenceExpression propertyReferenceEx, bool reportError)
+ {
+ Trace("LHS is property : {0}", propertyReferenceEx.PropertyName);
+ object lhs = DeserializeExpression(manager, null, propertyReferenceEx.TargetObject);
+
+ if (lhs != null && !(lhs is CodeExpression))
+ {
+ // Property assignments must go through our type descriptor system. However, we do not support parameterized properties. If there are any parameters on the property, we do not perform the assignment.
+ PropertyDescriptorCollection properties = GetPropertiesHelper(manager, lhs, runTimeProperties);
+ PropertyDescriptor p = properties[propertyReferenceEx.PropertyName];
+ if (p != null)
+ {
+ Trace("Processing RHS");
+ object rhs = DeserializeExpression(manager, null, statement.Right);
+ if (rhs is CodeExpression)
+ {
+ TraceError("Unable to simplify statement to anything better than: {0}", rhs.GetType().Name);
+ return false;
+ }
+
+ IConvertible ic = rhs as IConvertible;
+
+ if (ic != null && p.PropertyType != rhs.GetType())
+ {
+ try
+ {
+ rhs = ic.ToType(p.PropertyType, null);
+ }
+ catch
+ {
+ }
+ }
+
+ //We need to ensure that no virtual types leak into the runtime code
+ //So if we ever assign a property value to a Type -- we make sure that the Type is a
+ // real System.Type.
+ Type rhsType = rhs as Type;
+ if (rhsType != null && rhsType.UnderlyingSystemType != null)
+ {
+ rhs = rhsType.UnderlyingSystemType; //unwrap this "type" that came because it was not actually a real bcl type.
+ }
+
+ // Next: see if the RHS of this expression was a property reference too. If it was, then
+ // we will look for a MemberRelationshipService to record the relationship between these
+ // two properties, if supported.
+ // We need to setup this MemberRelationship before we actually set the property value.
+ // If we do it the other way around the new property value will be pushed into the old
+ // relationship, which isn't a problem during normal serialization (since it not very
+ // likely the property has already been assigned to), but it does affect undo.
+ MemberRelationship oldRelation = MemberRelationship.Empty;
+ MemberRelationshipService relationships = null;
+ if (statement.Right is CodePropertyReferenceExpression)
+ {
+ relationships = manager.GetService(typeof(MemberRelationshipService)) as MemberRelationshipService;
+
+ if (relationships != null)
+ {
+ CodePropertyReferenceExpression rhsPropRef = (CodePropertyReferenceExpression)statement.Right;
+ object rhsPropTarget = DeserializeExpression(manager, null, rhsPropRef.TargetObject);
+ PropertyDescriptor rhsProp = GetPropertiesHelper(manager, rhsPropTarget, null)[rhsPropRef.PropertyName];
+
+ if (rhsProp != null)
+ {
+ MemberRelationship source = new MemberRelationship(lhs, p);
+ MemberRelationship target = new MemberRelationship(rhsPropTarget, rhsProp);
+
+ oldRelation = relationships[source];
+
+ if (relationships.SupportsRelationship(source, target))
+ {
+ relationships[source] = target;
+ }
+ }
+ }
+ }
+ else
+ {
+ relationships = manager.GetService(typeof(MemberRelationshipService)) as MemberRelationshipService;
+
+ if (relationships != null)
+ {
+ oldRelation = relationships[lhs, p];
+ relationships[lhs, p] = MemberRelationship.Empty;
+ }
+ }
+
+ try
+ {
+ p.SetValue(lhs, rhs);
+ }
+ catch
+ {
+ if (relationships != null)
+ {
+ relationships[lhs, p] = oldRelation;
+ }
+ throw;
+ }
+ return true;
+ }
+ else
+ {
+ if (reportError)
+ {
+ TraceError("Object {0} does not have a property {1}", lhs.GetType().Name, propertyReferenceEx.PropertyName);
+ Error(manager, string.Format(SR.SerializerNoSuchProperty, lhs.GetType().FullName, propertyReferenceEx.PropertyName), SR.SerializerNoSuchProperty);
+ }
+ }
+ }
+ else
+ {
+ TraceWarning("Could not find target object for property {0}", propertyReferenceEx.PropertyName);
+ }
+ return false;
}
///
@@ -147,7 +2027,118 @@ protected void DeserializeStatement(IDesignerSerializationManager manager, CodeS
///
protected CodeExpression GetExpression(IDesignerSerializationManager manager, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ CodeExpression expression = null;
+
+ if (manager == null)
+ {
+ throw new ArgumentNullException("manager");
+ }
+
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ Trace("GetExpression called for object {0}", value.ToString());
+
+ // Is the expression part of a prior SetExpression call?
+ ExpressionTable table = manager.Context[typeof(ExpressionTable)] as ExpressionTable;
+
+ if (table != null)
+ {
+ expression = table.GetExpression(value);
+ TraceIf(expression != null, "Resolved through expression table : {0}", expression);
+ }
+
+ // Check to see if this object represents the root context.
+ if (expression == null)
+ {
+ RootContext rootEx = manager.Context[typeof(RootContext)] as RootContext;
+
+ if (rootEx != null && object.ReferenceEquals(rootEx.Value, value))
+ {
+ expression = rootEx.Expression;
+ TraceIf(expression != null, "Resolved through root expression context : {0}", expression);
+ }
+ }
+
+ // Now check IReferenceService.
+ if (expression == null)
+ {
+
+ // perf: first try to retrieve objectName from DesignerSerializationManager
+ // only then involve reference service if needed
+ // this is done to avoid unnecessary ensuring\creating references
+
+ string objectName = manager.GetName(value);
+ if (objectName == null || objectName.IndexOf('.') != -1)
+ {
+ IReferenceService refSvc = manager.GetService(typeof(IReferenceService)) as IReferenceService;
+ if (refSvc != null)
+ {
+ objectName = refSvc.GetName(value);
+ if (objectName != null && objectName.IndexOf('.') != -1)
+ {
+ Trace("Resolving through IReferenceService : {0}", objectName);
+
+ // This object name is built from sub objects. Assemble the graph of sub objects.
+ string[] nameParts = objectName.Split('.');
+
+ Debug.Assert(nameParts.Length > 0, "How can we fail to split when IndexOf succeeded?");
+
+ object baseInstance = manager.GetInstance(nameParts[0]);
+
+ TraceWarningIf(baseInstance == null, "Manager can't return an instance for object {0}", nameParts[0]);
+ if (baseInstance != null)
+ {
+ CodeExpression baseExpression = SerializeToExpression(manager, baseInstance);
+
+ TraceWarningIf(baseExpression == null, "Unable to serialize object {0} to an expression.", baseInstance);
+ if (baseExpression != null)
+ {
+ for (int idx = 1; idx < nameParts.Length; idx++)
+ {
+ baseExpression = new CodePropertyReferenceExpression(baseExpression, nameParts[idx]);
+ }
+
+ expression = baseExpression;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Finally, the expression context.
+ if (expression == null)
+ {
+ ExpressionContext cxt = manager.Context[typeof(ExpressionContext)] as ExpressionContext;
+ if (cxt != null && object.ReferenceEquals(cxt.PresetValue, value))
+ {
+ expression = cxt.Expression;
+ }
+ }
+
+ if (expression != null)
+ {
+ // set up cache dependencies
+ // we check to see if there is anything on the stack
+ // if there is we make the parent entry a dependency of the current entry
+ ComponentCache.Entry parentEntry = (ComponentCache.Entry)manager.Context[typeof(ComponentCache.Entry)];
+ ComponentCache cache = (ComponentCache)manager.Context[typeof(ComponentCache)];
+
+ if (parentEntry != null && parentEntry.Component != value /* don't make ourselves dependent with ourselves */ && cache != null)
+ {
+ ComponentCache.Entry entry = null;
+ entry = cache.GetEntryAll(value);
+ if (entry != null && parentEntry.Component != null)
+ {
+ entry.AddDependency(parentEntry.Component);
+ }
+ }
+ }
+
+ return expression;
}
///
@@ -158,7 +2149,92 @@ protected CodeExpression GetExpression(IDesignerSerializationManager manager, ob
///
protected CodeDomSerializer GetSerializer(IDesignerSerializationManager manager, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (manager == null)
+ {
+ throw new ArgumentNullException("manager");
+ }
+ if (value != null)
+ {
+ AttributeCollection valueAttributes = GetAttributesHelper(manager, value);
+ AttributeCollection typeAttributes = GetAttributesFromTypeHelper(manager, value.GetType());
+
+ if (valueAttributes.Count != typeAttributes.Count)
+ {
+ // Ok, someone has stuffed custom attributes on this instance. Since the serialization manager only takes types, we've got to see if one of these custom attributes is a designer serializer attribute.
+ string valueSerializerTypeName = null;
+ Type desiredSerializerType = typeof(CodeDomSerializer);
+ DesignerSerializationManager vsManager = manager as DesignerSerializationManager;
+ foreach (Attribute a in valueAttributes)
+ {
+ if (a is DesignerSerializerAttribute da)
+ {
+ Type realSerializerType;
+ if (vsManager != null)
+ {
+ realSerializerType = vsManager.GetRuntimeType(da.SerializerBaseTypeName);
+ }
+ else
+ {
+ realSerializerType = manager.GetType(da.SerializerBaseTypeName);
+ }
+
+ if (realSerializerType == desiredSerializerType)
+ {
+ valueSerializerTypeName = da.SerializerTypeName;
+ break;
+ }
+ }
+ }
+
+ // If we got a value serializer, we've got to do the same thing here for the type serializer. We only care if the two are different
+ if (valueSerializerTypeName != null)
+ {
+ foreach (Attribute a in typeAttributes)
+ {
+ if (a is DesignerSerializerAttribute da)
+ {
+ Type realSerializerType;
+ if (vsManager != null)
+ {
+ realSerializerType = vsManager.GetRuntimeType(da.SerializerBaseTypeName);
+ }
+ else
+ {
+ realSerializerType = manager.GetType(da.SerializerBaseTypeName);
+ }
+ if (realSerializerType == desiredSerializerType)
+ {
+ // Ok, we found a serializer. If it matches the one we found for the value, then we can still use the default implementation.
+ if (valueSerializerTypeName.Equals(da.SerializerTypeName))
+ {
+ valueSerializerTypeName = null;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Finally, if we got a value serializer, we need to create it and use it.
+ if (valueSerializerTypeName != null)
+ {
+ Type serializerType = vsManager != null ? vsManager.GetRuntimeType(valueSerializerTypeName) :
+ manager.GetType(valueSerializerTypeName);
+ if (serializerType != null && desiredSerializerType.IsAssignableFrom(serializerType))
+ {
+ return (CodeDomSerializer)Activator.CreateInstance(serializerType);
+ }
+ }
+ }
+ }
+
+ // for serializing null, we pass null to the serialization manager otherwise, external IDesignerSerializationProviders wouldn't be given a chance to serialize null their own special way.
+ Type t = null;
+ if (value != null)
+ {
+ t = value.GetType();
+ }
+ return (CodeDomSerializer)manager.GetSerializer(t, typeof(CodeDomSerializer));
}
///
@@ -169,13 +2245,13 @@ protected CodeDomSerializer GetSerializer(IDesignerSerializationManager manager,
///
protected CodeDomSerializer GetSerializer(IDesignerSerializationManager manager, Type valueType)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ return manager.GetSerializer(valueType, typeof(CodeDomSerializer)) as CodeDomSerializer;
}
[SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")]
protected bool IsSerialized(IDesignerSerializationManager manager, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ return IsSerialized(manager, value, false);
}
///
@@ -186,7 +2262,18 @@ protected bool IsSerialized(IDesignerSerializationManager manager, object value)
[SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")]
protected bool IsSerialized(IDesignerSerializationManager manager, object value, bool honorPreset)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ bool hasExpression = false;
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (value == null) throw new ArgumentNullException("value");
+
+ // Is the expression part of a prior SetExpression call?
+ if (manager.Context[typeof(ExpressionTable)] is ExpressionTable table && table.GetExpression(value) != null && (!honorPreset || !table.ContainsPresetExpression(value)))
+ {
+ hasExpression = true;
+ }
+ Trace("IsSerialized called for object {0} : {1}", value, hasExpression);
+ return hasExpression;
+
}
///
@@ -194,10 +2281,178 @@ protected bool IsSerialized(IDesignerSerializationManager manager, object value,
/// It is aware of instance descriptors and will return true for isComplete if the entire configuration for the
/// instance could be achieved.
///
- protected CodeExpression SerializeCreationExpression(IDesignerSerializationManager manager, object value,
- out bool isComplete)
+ protected CodeExpression SerializeCreationExpression(IDesignerSerializationManager manager, object value, out bool isComplete)
+ {
+ isComplete = false;
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (value == null) throw new ArgumentNullException("value");
+
+ TypeConverter converter = TypeDescriptor.GetConverter(value);
+ // See if there is an ExpressionContext with a preset value we're interested in. If so, that will dictate our creation expression.
+ if (manager.Context[typeof(ExpressionContext)] is ExpressionContext cxt && object.ReferenceEquals(cxt.PresetValue, value))
+ {
+ CodeExpression expression = cxt.Expression;
+ //Okay, we found a preset creation expression. We just need to find if it isComplete.
+ if (converter.CanConvertTo(typeof(InstanceDescriptor)))
+ {
+ if (converter.ConvertTo(value, typeof(InstanceDescriptor)) is InstanceDescriptor descriptor && descriptor.MemberInfo != null)
+ {
+ isComplete = descriptor.IsComplete;
+ }
+ }
+ return expression;
+ }
+
+ // See if there is an instance descriptor for this type.
+ if (converter.CanConvertTo(typeof(InstanceDescriptor)))
+ {
+ if (converter.ConvertTo(value, typeof(InstanceDescriptor)) is InstanceDescriptor descriptor && descriptor.MemberInfo != null)
+ {
+ isComplete = descriptor.IsComplete;
+ return SerializeInstanceDescriptor(manager, value, descriptor);
+ }
+ }
+
+ // see if this thing is serialiable
+ if (GetReflectionTypeHelper(manager, value).IsSerializable && !(value is IComponent && ((IComponent)value).Site != null))
+ {
+ CodeExpression expression = SerializeToResourceExpression(manager, value);
+ TraceIf(expression != null, "Serialized value as a resource.");
+ if (expression != null)
+ {
+ isComplete = true;
+ return expression;
+ }
+ }
+
+ // No instance descriptor. See if we can get to a public constructor that takes no arguments
+ ConstructorInfo ctor = GetReflectionTypeHelper(manager, value).GetConstructor(new Type[0]);
+ if (ctor != null)
+ {
+ isComplete = false;
+ return new CodeObjectCreateExpression(TypeDescriptor.GetClassName(value), new CodeExpression[0]);
+ }
+ // Nothing worked.
+ return null;
+ }
+
+ private CodeExpression SerializeInstanceDescriptor(IDesignerSerializationManager manager, object value, InstanceDescriptor descriptor)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ CodeExpression expression = null;
+ using (TraceScope("CodeDomSerializerBase::SerializeInstanceDescriptor"))
+ {
+ Trace("Member : {0}, args : {1}", descriptor.MemberInfo.Name, descriptor.Arguments.Count);
+ // Serialize all of the arguments.
+ CodeExpression[] arguments = new CodeExpression[descriptor.Arguments.Count];
+ object[] argumentValues = new object[arguments.Length];
+ ParameterInfo[] parameters = null;
+
+ if (arguments.Length > 0)
+ {
+ descriptor.Arguments.CopyTo(argumentValues, 0);
+ MethodBase mi = descriptor.MemberInfo as MethodBase;
+ if (mi != null)
+ {
+ parameters = mi.GetParameters();
+ }
+ }
+
+ bool paramsOk = true;
+ for (int i = 0; i < arguments.Length; i++)
+ {
+ Debug.Assert(argumentValues != null && parameters != null, "These should have been allocated when the argument array was created.");
+ object arg = argumentValues[i];
+ CodeExpression exp = null;
+ ExpressionContext newCxt = null;
+
+ // If there is an ExpressionContext on the stack, we need to fix up its type to be the parameter type, so the argument objects get serialized correctly.
+ if (manager.Context[typeof(ExpressionContext)] is ExpressionContext cxt)
+ {
+ newCxt = new ExpressionContext(cxt.Expression, parameters[i].ParameterType, cxt.Owner);
+ manager.Context.Push(newCxt);
+ }
+
+ try
+ {
+ exp = SerializeToExpression(manager, arg);
+ }
+ finally
+ {
+ if (newCxt != null)
+ {
+ Debug.Assert(manager.Context.Current == newCxt, "Context stack corrupted.");
+ manager.Context.Pop();
+ }
+ }
+
+ if (exp != null)
+ {
+ // Assign over. See if we need a cast first.
+ if (arg != null && !parameters[i].ParameterType.IsAssignableFrom(arg.GetType()))
+ {
+ exp = new CodeCastExpression(parameters[i].ParameterType, exp);
+ }
+ arguments[i] = exp;
+ }
+ else
+ {
+ TraceWarning("Parameter {0} in instance descriptor call {1} could not be serialized.", i, descriptor.GetType().Name);
+ paramsOk = false;
+ break;
+ }
+ }
+
+ if (paramsOk)
+ {
+ Type expressionType = descriptor.MemberInfo.DeclaringType;
+ CodeTypeReference typeRef = new CodeTypeReference(expressionType);
+
+ if (descriptor.MemberInfo is ConstructorInfo)
+ {
+ expression = new CodeObjectCreateExpression(typeRef, arguments);
+ }
+ else if (descriptor.MemberInfo is MethodInfo)
+ {
+ CodeTypeReferenceExpression typeRefExp = new CodeTypeReferenceExpression(typeRef);
+ CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression(typeRefExp, descriptor.MemberInfo.Name);
+ expression = new CodeMethodInvokeExpression(methodRef, arguments);
+ expressionType = ((MethodInfo)descriptor.MemberInfo).ReturnType;
+ }
+ else if (descriptor.MemberInfo is PropertyInfo)
+ {
+ CodeTypeReferenceExpression typeRefExp = new CodeTypeReferenceExpression(typeRef);
+ CodePropertyReferenceExpression propertyRef = new CodePropertyReferenceExpression(typeRefExp, descriptor.MemberInfo.Name);
+ Debug.Assert(arguments.Length == 0, "Property serialization does not support arguments");
+ expression = propertyRef;
+ expressionType = ((PropertyInfo)descriptor.MemberInfo).PropertyType;
+ }
+ else if (descriptor.MemberInfo is FieldInfo)
+ {
+ Debug.Assert(arguments.Length == 0, "Field serialization does not support arguments");
+ CodeTypeReferenceExpression typeRefExp = new CodeTypeReferenceExpression(typeRef);
+ expression = new CodeFieldReferenceExpression(typeRefExp, descriptor.MemberInfo.Name);
+ expressionType = ((FieldInfo)descriptor.MemberInfo).FieldType;
+ }
+ else
+ {
+ Debug.Fail("Unrecognized reflection type in instance descriptor: " + descriptor.MemberInfo.GetType().Name);
+ }
+
+ // Finally, check to see if our value is assignable from the expression type. If not, then supply a cast. The value may be an internal or protected type; if it is, then walk up its hierarchy until we find one that is public.
+ Type targetType = value.GetType();
+ while (!targetType.IsPublic)
+ {
+ targetType = targetType.BaseType;
+ }
+
+ if (!targetType.IsAssignableFrom(expressionType))
+ {
+ Trace("Supplying cast from {0} to {1}.", expressionType.Name, targetType.Name);
+ expression = new CodeCastExpression(targetType, expression);
+ }
+ }
+ }
+ return expression;
}
///
@@ -210,34 +2465,150 @@ protected CodeExpression SerializeCreationExpression(IDesignerSerializationManag
///
protected string GetUniqueName(IDesignerSerializationManager manager, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (value == null) throw new ArgumentNullException("value");
+
+ string name = manager.GetName(value);
+ if (name == null)
+ {
+ string baseName;
+ Type targetType = GetReflectionTypeHelper(manager, value);
+ INameCreationService ns = manager.GetService(typeof(INameCreationService)) as INameCreationService;
+ TraceWarningIf(ns == null, "Need to generate a unique name but we have no name creation service.");
+ if (ns != null)
+ {
+ baseName = ns.CreateName(null, targetType);
+ }
+ else
+ {
+ baseName = targetType.Name.ToLower(CultureInfo.InvariantCulture);
+ }
+
+ int suffixIndex = 1;
+ ComponentCache cache = manager.Context[typeof(ComponentCache)] as ComponentCache;
+ // Declare this name to the serializer. If there is already a name defined, keep trying.
+ while (true)
+ {
+ name = string.Format(CultureInfo.CurrentCulture, "{0}{1}", baseName, suffixIndex);
+ if (manager.GetInstance(name) == null && (cache == null || !cache.ContainsLocalName(name)))
+ {
+ manager.SetName(value, name);
+ if (manager.Context[typeof(ComponentCache.Entry)] is ComponentCache.Entry entry)
+ {
+ entry.AddLocalName(name);
+ }
+ break;
+ }
+ suffixIndex++;
+ }
+ }
+ return name;
}
///
/// This serializes a single event for the given object.
///
- protected void SerializeEvent(IDesignerSerializationManager manager, CodeStatementCollection statements,
- object value, EventDescriptor descriptor)
+ protected void SerializeEvent(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, EventDescriptor descriptor)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (statements == null) throw new ArgumentNullException("statements");
+ if (value == null) throw new ArgumentNullException("value");
+ if (descriptor == null) throw new ArgumentNullException("descriptor");
+
+ using (TraceScope("CodeDomSerializerBase::SerializeEvent"))
+ {
+ Trace("Name: {0}", descriptor.Name);
+ // Now look for a MemberCodeDomSerializer for the property. If we can't find one, then we can't serialize the property
+ manager.Context.Push(statements);
+ manager.Context.Push(descriptor);
+ try
+ {
+ MemberCodeDomSerializer memberSerializer = (MemberCodeDomSerializer)manager.GetSerializer(descriptor.GetType(), typeof(MemberCodeDomSerializer));
+
+ TraceErrorIf(memberSerializer == null, "Event {0} cannot be serialized because it has no serializer.", descriptor.Name);
+ if (memberSerializer != null && memberSerializer.ShouldSerialize(manager, value, descriptor))
+ {
+ memberSerializer.Serialize(manager, value, descriptor, statements);
+ }
+ }
+ finally
+ {
+ Debug.Assert(manager.Context.Current == descriptor, "Context stack corrupted.");
+ manager.Context.Pop();
+ manager.Context.Pop();
+ }
+ }
}
///
/// This serializes all events for the given object.
///
- protected void SerializeEvents(IDesignerSerializationManager manager, CodeStatementCollection statements,
- object value, params Attribute[] filter)
+ protected void SerializeEvents(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, params Attribute[] filter)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ Trace("CodeDomSerializerBase::SerializeEvents");
+ EventDescriptorCollection events = GetEventsHelper(manager, value, filter).Sort();
+ foreach (EventDescriptor evt in events)
+ {
+ SerializeEvent(manager, statements, value, evt);
+ }
}
///
/// This serializes all properties for the given object, using the provided filter.
///
- protected void SerializeProperties(IDesignerSerializationManager manager, CodeStatementCollection statements,
- object value, Attribute[] filter)
+ protected void SerializeProperties(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, Attribute[] filter)
+ {
+ using (TraceScope("CodeDomSerializerBase::SerializeProperties"))
+ {
+ PropertyDescriptorCollection properties = GetFilteredProperties(manager, value, filter).Sort();
+ InheritanceAttribute inheritance = (InheritanceAttribute)GetAttributesHelper(manager, value)[typeof(InheritanceAttribute)];
+
+ if (inheritance == null)
+ {
+ inheritance = InheritanceAttribute.NotInherited;
+ }
+
+ manager.Context.Push(inheritance);
+ try
+ {
+ foreach (PropertyDescriptor property in properties)
+ {
+ if (!property.Attributes.Contains(DesignerSerializationVisibilityAttribute.Hidden))
+ {
+ SerializeProperty(manager, statements, value, property);
+ }
+ }
+ }
+ finally
+ {
+ Debug.Assert(manager.Context.Current == inheritance, "Sombody messed up our context stack.");
+ manager.Context.Pop();
+ }
+ }
+ }
+ private PropertyDescriptorCollection GetFilteredProperties(IDesignerSerializationManager manager, object value, Attribute[] filter)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ IComponent comp = value as IComponent;
+ PropertyDescriptorCollection props = GetPropertiesHelper(manager, value, filter);
+ if (comp != null)
+ {
+ if (((IDictionary)props).IsReadOnly)
+ {
+ PropertyDescriptor[] propArray = new PropertyDescriptor[props.Count];
+ props.CopyTo(propArray, 0);
+ props = new PropertyDescriptorCollection(propArray);
+ }
+
+ PropertyDescriptor filterProp = manager.Properties["FilteredProperties"];
+ if (filterProp != null)
+ {
+ if (filterProp.GetValue(manager) is ITypeDescriptorFilterService filterSvc)
+ {
+ filterSvc.FilterProperties(comp, props);
+ }
+ }
+ }
+ return props;
}
///
@@ -245,19 +2616,89 @@ protected void SerializeProperties(IDesignerSerializationManager manager, CodeSt
/// property in a resource blob. This is useful for deserializing properties that cannot be represented
/// in code, such as design-time properties.
///
- protected void SerializePropertiesToResources(IDesignerSerializationManager manager,
- CodeStatementCollection statements, object value, Attribute[] filter)
+ protected void SerializePropertiesToResources(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, Attribute[] filter)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ using (TraceScope("ComponentCodeDomSerializerBase::SerializePropertiesToResources"))
+ {
+ PropertyDescriptorCollection props = GetPropertiesHelper(manager, value, filter);
+ manager.Context.Push(statements);
+ try
+ {
+ CodeExpression target = SerializeToExpression(manager, value);
+ if (target != null)
+ {
+ CodePropertyReferenceExpression propertyRef = new CodePropertyReferenceExpression(target, string.Empty);
+ foreach (PropertyDescriptor property in props)
+ {
+ TraceWarningIf(property.Attributes.Contains(DesignerSerializationVisibilityAttribute.Content), "PersistContents property " + property.Name + " cannot be serialized to resources.");
+ ExpressionContext tree = new ExpressionContext(propertyRef, property.PropertyType, value);
+ manager.Context.Push(tree);
+ try
+ {
+ if (property.Attributes.Contains(DesignerSerializationVisibilityAttribute.Visible))
+ {
+ propertyRef.PropertyName = property.Name;
+ Trace("Property : {0}", property.Name);
+
+ string name;
+ if (target is CodeThisReferenceExpression)
+ {
+ name = "$this";
+ }
+ else
+ {
+ name = manager.GetName(value);
+ }
+
+ name = string.Format(CultureInfo.CurrentCulture, "{0}.{1}", name, property.Name);
+ ResourceCodeDomSerializer.GetDefault().SerializeMetadata(manager, name, property.GetValue(value), property.ShouldSerializeValue(value));
+ }
+ }
+ finally
+ {
+ Debug.Assert(manager.Context.Current == tree, "Context stack corrupted.");
+ manager.Context.Pop();
+ }
+ }
+ }
+ }
+ finally
+ {
+ Debug.Assert(manager.Context.Current == statements, "Context stack corrupted.");
+ manager.Context.Pop();
+ }
+ }
}
///
/// This serializes the given proeprty for the given object.
///
- protected void SerializeProperty(IDesignerSerializationManager manager, CodeStatementCollection statements,
- object value, PropertyDescriptor propertyToSerialize)
+ protected void SerializeProperty(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, PropertyDescriptor propertyToSerialize)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (value == null) throw new ArgumentNullException("value");
+ if (propertyToSerialize == null) throw new ArgumentNullException("propertyToSerialize");
+ if (statements == null) throw new ArgumentNullException("statements");
+
+ Trace("CodeDomSerializerBase::SerializeProperty {0}", propertyToSerialize.Name);
+ // Now look for a MemberCodeDomSerializer for the property. If we can't find one, then we can't serialize the property
+ manager.Context.Push(statements);
+ manager.Context.Push(propertyToSerialize);
+ try
+ {
+ MemberCodeDomSerializer memberSerializer = (MemberCodeDomSerializer)manager.GetSerializer(propertyToSerialize.GetType(), typeof(MemberCodeDomSerializer));
+ TraceErrorIf(memberSerializer == null, "Property {0} cannot be serialized because it has no serializer.", propertyToSerialize.Name);
+ if (memberSerializer != null && memberSerializer.ShouldSerialize(manager, value, propertyToSerialize))
+ {
+ memberSerializer.Serialize(manager, value, propertyToSerialize, statements);
+ }
+ }
+ finally
+ {
+ Debug.Assert(manager.Context.Current == propertyToSerialize, "Context stack corrupted.");
+ manager.Context.Pop();
+ manager.Context.Pop();
+ }
}
///
@@ -266,17 +2707,16 @@ protected void SerializeProperty(IDesignerSerializationManager manager, CodeStat
///
protected void SerializeResource(IDesignerSerializationManager manager, string resourceName, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ ResourceCodeDomSerializer.GetDefault().WriteResource(manager, resourceName, value);
}
///
/// Writes the given resource value under the given name. The resource is written to the
/// invariant culture.
///
- protected void SerializeResourceInvariant(IDesignerSerializationManager manager, string resourceName,
- object value)
+ protected void SerializeResourceInvariant(IDesignerSerializationManager manager, string resourceName, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ ResourceCodeDomSerializer.GetDefault().WriteResourceInvariant(manager, resourceName, value);
}
///
@@ -296,7 +2736,215 @@ protected void SerializeResourceInvariant(IDesignerSerializationManager manager,
///
protected CodeExpression SerializeToExpression(IDesignerSerializationManager manager, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ CodeExpression expression = null;
+
+ using (TraceScope("SerializeToExpression"))
+ {
+ // We do several things here:
+ // First, we check to see if there is already an expression for this object by calling IsSerialized / GetExpression.
+ // Failing that we check GetLegacyExpression to see if we are working with an old serializer.
+ // Failing that, we invoke the object's serializer. If that serializer returned a CodeExpression, we will use it.
+ // If the serializer did not return a code expression, we call GetExpression one last time to see if the serializer added an expression. If it did, we use it. Otherwise we return null.
+ // If the serializer was invoked and it created one or more statements those statements will be added to a statement collection. Additionally, if there is a statement context that contains a statement table for this object we will push that statement table onto the context stack in case someone else needs statements.
+ if (value != null)
+ {
+ if (IsSerialized(manager, value))
+ {
+ expression = GetExpression(manager, value);
+ TraceIf(expression != null, "Existing expression found : {0}", expression);
+ }
+ else
+ {
+ expression = GetLegacyExpression(manager, value);
+ if (expression != null)
+ {
+ TraceWarning("Using legacy expression guard to prevent recursion. Serializer for {0} should be rewritten to handle GetExpression / SetExpression.", value);
+ SetExpression(manager, value, expression);
+ }
+ }
+ }
+
+ if (expression == null)
+ {
+ CodeDomSerializer serializer = GetSerializer(manager, value);
+ if (serializer != null)
+ {
+ Trace("Invoking serializer {0}", serializer.GetType().Name);
+ CodeStatementCollection saveStatements = null;
+ if (value != null)
+ {
+ // The Whidbey model for serializing a complex object is to call SetExpression with the object's reference expression and then call on the various Serialize Property / Event methods. This is incompatible with legacy code, and if not handled legacy code may serialize incorrectly or even stack fault. To handle this, we keep a private "Legacy Expression Table". This is a table that we fill in here. We don't fill in the actual legacy expression here. Rather, we fill it with a marker value and obtain the legacy expression above in GetLegacyExpression. If we hit this case, we then save the expression in GetExpression so that future calls to IsSerialized will succeed.
+ SetLegacyExpression(manager, value);
+ if (manager.Context[typeof(StatementContext)] is StatementContext statementCxt)
+ {
+ saveStatements = statementCxt.StatementCollection[value];
+ }
+
+ if (saveStatements != null)
+ {
+ manager.Context.Push(saveStatements);
+ }
+ }
+
+ object result = null;
+ try
+ {
+ result = serializer.Serialize(manager, value);
+ }
+ finally
+ {
+ if (saveStatements != null)
+ {
+ Debug.Assert(manager.Context.Current == saveStatements, "Context stack corrupted.");
+ manager.Context.Pop();
+ }
+ }
+
+ expression = result as CodeExpression;
+ if (expression == null && value != null)
+ {
+ expression = GetExpression(manager, value);
+ }
+
+ // If the result is a statement or a group of statements, we need to see if there is a code statement collection on the stack we can push the statements into.
+ CodeStatementCollection statements = result as CodeStatementCollection;
+ if (statements == null)
+ {
+ if (result is CodeStatement statement)
+ {
+ statements = new CodeStatementCollection
+ {
+ statement
+ };
+ }
+ }
+
+ if (statements != null)
+ {
+ Trace("Serialization produced additional statements");
+ // See if we have a place for these statements to be stored. If not, then check the context.
+ if (saveStatements == null)
+ {
+ saveStatements = manager.Context[typeof(CodeStatementCollection)] as CodeStatementCollection;
+ }
+
+ if (saveStatements != null)
+ {
+ Trace("Saving in context stack statement collection");
+ Debug.Assert(saveStatements != statements, "The serializer returned the same collection that exists on the context stack.");
+ saveStatements.AddRange(statements);
+ }
+ else
+ {
+ // If we got here we will be losing data because we have no avenue to save these statements. Inform the user.
+ string valueName = "(null)";
+ if (value != null)
+ {
+ valueName = manager.GetName(value);
+ if (valueName == null)
+ {
+ valueName = value.GetType().Name;
+ }
+ }
+ TraceError("Serialization produced a set of statements but there is no statement collection on the stack to receive them.");
+ manager.ReportError(string.Format(SR.SerializerLostStatements, valueName));
+ }
+ }
+ }
+ else
+ {
+ TraceError("No serializer for data type: {0}", (value == null ? "(null)" : value.GetType().Name));
+ manager.ReportError(string.Format(SR.SerializerNoSerializerForComponent, value.GetType().FullName));
+ }
+ }
+ }
+ return expression;
+ }
+
+ private CodeExpression GetLegacyExpression(IDesignerSerializationManager manager, object value)
+ {
+ CodeExpression expression = null;
+ if (manager.Context[typeof(LegacyExpressionTable)] is LegacyExpressionTable table)
+ {
+ object exp = table[value];
+ if (exp == value)
+ {
+ // Sentinel. Compute an actual legacy expression to store.
+ string name = manager.GetName(value);
+ bool referenceName = false;
+ if (name == null)
+ {
+ IReferenceService referenceService = (IReferenceService)manager.GetService(typeof(IReferenceService));
+ if (referenceService != null)
+ {
+ name = referenceService.GetName(value);
+ referenceName = name != null;
+ }
+ }
+
+ if (name != null)
+ {
+ Trace("Object is reference ({0}) Creating reference expression", name);
+ // Check to see if this is a reference to the root component. If it is, then use "this".
+ RootContext root = (RootContext)manager.Context[typeof(RootContext)];
+ if (root != null)
+ {
+ if (root.Value == value)
+ {
+ expression = root.Expression;
+ }
+ else if (referenceName && name.IndexOf('.') != -1)
+ {
+ // if it's a reference name with a dot, we've actually got a property here...
+ int dotIndex = name.IndexOf('.');
+
+ expression = new CodePropertyReferenceExpression(new CodeFieldReferenceExpression(root.Expression, name.Substring(0, dotIndex)), name.Substring(dotIndex + 1));
+ }
+ else
+ {
+ expression = new CodeFieldReferenceExpression(root.Expression, name);
+ }
+ }
+ else
+ {
+ // A variable reference
+ if (referenceName && name.IndexOf('.') != -1)
+ {
+ // if it's a reference name with a dot, we've actually got a property here...
+ int dotIndex = name.IndexOf('.');
+ expression = new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(name.Substring(0, dotIndex)), name.Substring(dotIndex + 1));
+ }
+ else
+ {
+ expression = new CodeVariableReferenceExpression(name);
+ }
+ }
+ }
+ table[value] = expression;
+ }
+ else
+ {
+ expression = exp as CodeExpression;
+ }
+ }
+ return expression;
+ }
+
+ private void SetLegacyExpression(IDesignerSerializationManager manager, object value)
+ {
+ if (value is IComponent)
+ {
+ LegacyExpressionTable table = (LegacyExpressionTable)manager.Context[typeof(LegacyExpressionTable)];
+ if (table == null)
+ {
+ table = new LegacyExpressionTable();
+ manager.Context.Append(table);
+ }
+ table[value] = value;
+ }
+ }
+ private class LegacyExpressionTable : Hashtable
+ {
}
///
@@ -309,7 +2957,7 @@ protected CodeExpression SerializeToExpression(IDesignerSerializationManager man
///
protected CodeExpression SerializeToResourceExpression(IDesignerSerializationManager manager, object value)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ return SerializeToResourceExpression(manager, value, true);
}
///
@@ -320,16 +2968,45 @@ protected CodeExpression SerializeToResourceExpression(IDesignerSerializationMan
/// false to ensureInvariant when you intend to read resources differently than directly asking for a value.
/// The default value of insureInvariant is true.
///
- protected CodeExpression SerializeToResourceExpression(IDesignerSerializationManager manager, object value,
- bool ensureInvariant)
+ protected CodeExpression SerializeToResourceExpression(IDesignerSerializationManager manager, object value, bool ensureInvariant)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ CodeExpression result = null;
+ if (value == null || value.GetType().IsSerializable)
+ {
+ CodeStatementCollection saveStatements = null;
+ if (value != null)
+ {
+ if (manager.Context[typeof(StatementContext)] is StatementContext statementCxt)
+ {
+ saveStatements = statementCxt.StatementCollection[value];
+ }
+
+ if (saveStatements != null)
+ {
+ manager.Context.Push(saveStatements);
+ }
+ }
+
+ try
+ {
+ result = ResourceCodeDomSerializer.GetDefault().Serialize(manager, value, false, ensureInvariant) as CodeExpression;
+ }
+ finally
+ {
+ if (saveStatements != null)
+ {
+ Debug.Assert(manager.Context.Current == saveStatements, "Context stack corrupted.");
+ manager.Context.Pop();
+ }
+ }
+ }
+ return result;
}
[SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")]
protected void SetExpression(IDesignerSerializationManager manager, object value, CodeExpression expression)
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ SetExpression(manager, value, expression, false);
}
///
@@ -339,10 +3016,284 @@ protected void SetExpression(IDesignerSerializationManager manager, object value
/// GetExpression method.
///
[SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")]
- protected void SetExpression(IDesignerSerializationManager manager, object value, CodeExpression expression,
- bool isPreset)
+ protected void SetExpression(IDesignerSerializationManager manager, object value, CodeExpression expression, bool isPreset)
+ {
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (value == null) throw new ArgumentNullException("value");
+ if (expression == null) throw new ArgumentNullException("expression");
+
+ ExpressionTable table = (ExpressionTable)manager.Context[typeof(ExpressionTable)];
+ if (table == null)
+ {
+ table = new ExpressionTable();
+ manager.Context.Append(table);
+ }
+ Trace("Set expression {0} for object {1}", expression, value);
+ // in debug builds, save off who performed this set expression. It's very valuable to know.
+#if DEBUG
+ if (traceSerialization.TraceVerbose)
+ {
+ expression.UserData["StackTrace"] = Environment.StackTrace;
+ }
+ else
+ {
+ // Default to off as snapping the stack takes too much time in DEBUG to leave on permanently.
+ expression.UserData["StackTrace"] = "To enable - turn on DesignerSerialization TraceSwitch";
+ }
+
+ CodeExpression existingExpression = table.GetExpression(value);
+ if (existingExpression != null && !isPreset)
+ {
+ Debug.Fail("There shouldn't be an expression already associated with this object : " + manager.GetName(value));
+ if (!(existingExpression.UserData["StackTrace"] is string stack))
+ {
+ stack = "unknown";
+ }
+ TraceWarning("Duplicate expression on context stack for value {0}. Original expression callstack: {1}", value, stack);
+ }
+#endif
+ table.SetExpression(value, expression, isPreset);
+ }
+
+ internal static void FillStatementTable(IDesignerSerializationManager manager, IDictionary table, CodeStatementCollection statements)
+ {
+ FillStatementTable(manager, table, null, statements, null);
+ }
+
+ internal static void FillStatementTable(IDesignerSerializationManager manager, IDictionary table, Dictionary names, CodeStatementCollection statements, string className)
+ {
+ using (TraceScope("CodeDomSerializerBase::FillStatementTable"))
+ {
+ // Look in the method body to try to find statements with a LHS that points to a name in our nametable.
+ foreach (CodeStatement statement in statements)
+ {
+ CodeExpression expression = null;
+ if (statement is CodeAssignStatement assign)
+ {
+ Trace("Processing CodeAssignStatement");
+ expression = assign.Left;
+ }
+ else if (statement is CodeAttachEventStatement attachEvent)
+ {
+ Trace("Processing CodeAttachEventStatement");
+ expression = attachEvent.Event;
+ }
+ else if (statement is CodeRemoveEventStatement removeEvent)
+ {
+ Trace("Processing CodeRemoveEventStatement");
+ expression = removeEvent.Event;
+ }
+ else if (statement is CodeExpressionStatement expressionStmt)
+ {
+ Trace("Processing CodeExpressionStatement");
+ expression = expressionStmt.Expression;
+ }
+ else if (statement is CodeVariableDeclarationStatement variableDecl)
+ {
+ Trace("Processing CodeVariableDeclarationStatement");
+ AddStatement(table, variableDecl.Name, variableDecl);
+ if (names != null && variableDecl.Type != null && !string.IsNullOrEmpty(variableDecl.Type.BaseType))
+ {
+ names[variableDecl.Name] = GetTypeNameFromCodeTypeReference(manager, variableDecl.Type);
+ }
+ expression = null;
+ }
+
+ // Expressions we look for.
+ CodeDelegateCreateExpression delegateCreateEx;
+ CodeDelegateInvokeExpression delegateInvokeEx;
+ CodeDirectionExpression directionEx;
+ CodeEventReferenceExpression eventReferenceEx;
+ CodeMethodInvokeExpression methodInvokeEx;
+ CodeMethodReferenceExpression methodReferenceEx;
+ CodeArrayIndexerExpression arrayIndexerEx;
+ CodeFieldReferenceExpression fieldReferenceEx;
+ CodePropertyReferenceExpression propertyReferenceEx;
+ CodeVariableReferenceExpression variableReferenceEx;
+
+ if (expression != null)
+ {
+ // Simplify the expression as much as we can, looking for our target object in the process. If we find an expression that refers to our target object, we're done and can move on to the next statement.
+ while (true)
+ {
+ if (expression is CodeCastExpression castEx)
+ {
+ Trace("Simplifying CodeCastExpression");
+ expression = castEx.Expression;
+ }
+ else if ((delegateCreateEx = expression as CodeDelegateCreateExpression) != null)
+ {
+ Trace("Simplifying CodeDelegateCreateExpression");
+ expression = delegateCreateEx.TargetObject;
+ }
+ else if ((delegateInvokeEx = expression as CodeDelegateInvokeExpression) != null)
+ {
+ Trace("Simplifying CodeDelegateInvokeExpression");
+ expression = delegateInvokeEx.TargetObject;
+ }
+ else if ((directionEx = expression as CodeDirectionExpression) != null)
+ {
+ Trace("Simplifying CodeDirectionExpression");
+ expression = directionEx.Expression;
+ }
+ else if ((eventReferenceEx = expression as CodeEventReferenceExpression) != null)
+ {
+ Trace("Simplifying CodeEventReferenceExpression");
+ expression = eventReferenceEx.TargetObject;
+ }
+ else if ((methodInvokeEx = expression as CodeMethodInvokeExpression) != null)
+ {
+ Trace("Simplifying CodeMethodInvokeExpression");
+ expression = methodInvokeEx.Method;
+ }
+ else if ((methodReferenceEx = expression as CodeMethodReferenceExpression) != null)
+ {
+ Trace("Simplifying CodeMethodReferenceExpression");
+ expression = methodReferenceEx.TargetObject;
+ }
+ else if ((arrayIndexerEx = expression as CodeArrayIndexerExpression) != null)
+ {
+ Trace("Simplifying CodeArrayIndexerExpression");
+ expression = arrayIndexerEx.TargetObject;
+ }
+ else if ((fieldReferenceEx = expression as CodeFieldReferenceExpression) != null)
+ {
+ // For fields we need to check to see if the field name is equal to the target object. If it is, then we have the expression we want. We can add the statement here and then break out of our loop.
+ // Note: We cannot validate that this is a name in our nametable. The nametable only contains names we have discovered through code parsing and will not include data from any inherited objects. We accept the field now, and then fail later if we try to resolve it to an object and we can't find it.
+ bool addedStatement = false;
+ if (fieldReferenceEx.TargetObject is CodeThisReferenceExpression)
+ {
+ Type type = GetType(manager, fieldReferenceEx.FieldName, names);
+ if (type != null)
+ {
+ if (manager.GetSerializer(type, typeof(CodeDomSerializer)) is CodeDomSerializer serializer)
+ {
+ string componentName = serializer.GetTargetComponentName(statement, expression, type);
+ if (!string.IsNullOrEmpty(componentName))
+ {
+ AddStatement(table, componentName, statement);
+ addedStatement = true;
+ }
+ }
+ }
+ if (!addedStatement)
+ {
+ // we still want to do this in case of the "Note" above.
+ AddStatement(table, fieldReferenceEx.FieldName, statement);
+ }
+ break;
+ }
+ else
+ {
+ Trace("Simplifying CodeFieldReferenceExpression");
+ expression = fieldReferenceEx.TargetObject;
+ }
+ }
+ else if ((propertyReferenceEx = expression as CodePropertyReferenceExpression) != null)
+ {
+ // For properties we need to check to see if the property name is equal to the target object. If it is, then we have the expression we want. We can add the statement here and then break out of our loop.
+ if (propertyReferenceEx.TargetObject is CodeThisReferenceExpression && (names == null || names.ContainsKey(propertyReferenceEx.PropertyName)))
+ {
+ AddStatement(table, propertyReferenceEx.PropertyName, statement);
+ break;
+ }
+ else
+ {
+ Trace("Simplifying CodePropertyReferenceExpression");
+ expression = propertyReferenceEx.TargetObject;
+ }
+ }
+ else if ((variableReferenceEx = expression as CodeVariableReferenceExpression) != null)
+ {
+ // For variables we need to check to see if the variable name is equal to the target object. If it is, then we have the expression we want. We can add the statement here and then break out of our loop.
+ bool statementAdded = false;
+ if (names != null)
+ {
+ Type type = GetType(manager, variableReferenceEx.VariableName, names);
+ if (type != null)
+ {
+ if (manager.GetSerializer(type, typeof(CodeDomSerializer)) is CodeDomSerializer serializer)
+ {
+ string componentName = serializer.GetTargetComponentName(statement, expression, type);
+ if (!string.IsNullOrEmpty(componentName))
+ {
+ AddStatement(table, componentName, statement);
+ statementAdded = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ AddStatement(table, variableReferenceEx.VariableName, statement);
+ statementAdded = true;
+ }
+ if (!statementAdded)
+ {
+ TraceError("Variable {0} used before it was declared.", variableReferenceEx.VariableName);
+ manager.ReportError(new CodeDomSerializerException(string.Format(SR.SerializerUndeclaredName, variableReferenceEx.VariableName), manager));
+ }
+ break;
+ }
+ else if (expression is CodeThisReferenceExpression || expression is CodeBaseReferenceExpression)
+ {
+ // We cannot go any further than "this". So, we break out of the loop. We file this statement under the root object.
+ Debug.Assert(className != null, "FillStatementTable expected a valid className but received null");
+ if (className != null)
+ {
+ AddStatement(table, className, statement);
+ }
+ break;
+ }
+ else
+ {
+ // We cannot simplify this expression any further, so we stop looping.
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ internal static Type GetType(IDesignerSerializationManager manager, string name, Dictionary names)
+ {
+ Type type = null;
+ if (names != null && names.ContainsKey(name))
+ {
+ string typeName = names[name];
+ if (manager != null && !string.IsNullOrEmpty(typeName))
+ {
+ type = manager.GetType(typeName);
+ }
+ }
+ return type;
+ }
+
+ private static void AddStatement(IDictionary table, string name, CodeStatement statement)
+ {
+
+ OrderedCodeStatementCollection statements;
+ if (table.Contains(name))
+ {
+ statements = (OrderedCodeStatementCollection)table[name];
+ }
+ else
+ {
+ // push in an order key so we know what position this item was in the list of declarations. this allows us to preserve ZOrder.
+ statements = new OrderedCodeStatementCollection
+ {
+ Order = table.Count,
+ Name = name
+ };
+ table[name] = statements;
+ }
+ statements.Add(statement);
+ }
+
+ internal class OrderedCodeStatementCollection : CodeStatementCollection
{
- throw new NotImplementedException(SR.NotImplementedByDesign);
+ public int Order;
+ public string Name;
}
}
}
diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerException.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerException.cs
new file mode 100644
index 00000000000..0f93edcecaa
--- /dev/null
+++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeDomSerializerException.cs
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.CodeDom;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Serialization;
+
+namespace System.ComponentModel.Design.Serialization
+{
+ ///
+ /// The exception that is thrown when the code dom serializer experiences an error.
+ ///
+ [Serializable]
+ [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")]
+ public class CodeDomSerializerException : SystemException
+ {
+
+ private readonly CodeLinePragma _linePragma;
+
+ ///
+ /// Initializes a new instance of the CodeDomSerializerException class.
+ ///
+ public CodeDomSerializerException(string message, CodeLinePragma linePragma) : base(message)
+ {
+ _linePragma = linePragma;
+ }
+
+ ///
+ /// Initializes a new instance of the CodeDomSerializerException class.
+ ///
+ public CodeDomSerializerException(Exception ex, CodeLinePragma linePragma) : base(ex.Message, ex)
+ {
+ _linePragma = linePragma;
+ }
+
+ ///
+ /// Initializes a new instance of the CodeDomSerializerException class.
+ ///
+ public CodeDomSerializerException(string message, IDesignerSerializationManager manager) : base(message)
+ {
+ FillLinePragmaFromContext(manager);
+ }
+
+ ///
+ /// Initializes a new instance of the CodeDomSerializerException class.
+ ///
+ public CodeDomSerializerException(Exception ex, IDesignerSerializationManager manager) : base(ex.Message, ex)
+ {
+ FillLinePragmaFromContext(manager);
+ }
+
+ protected CodeDomSerializerException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ _linePragma = (CodeLinePragma)info.GetValue("linePragma", typeof(CodeLinePragma));
+ }
+
+ ///
+ /// Gets the line pragma object that is related to this error.
+ ///
+ public CodeLinePragma LinePragma
+ {
+ get => _linePragma;
+ }
+
+ ///
+ /// Sniffs around in the context looking for a code statement. if it finds one, it will add the statement's line # information to the exception.
+ ///
+ private void FillLinePragmaFromContext(IDesignerSerializationManager manager)
+ {
+ if (manager == null)
+ throw new ArgumentNullException("manager");
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException("info");
+ }
+ info.AddValue("linePragma", _linePragma);
+ base.GetObjectData(info, context);
+ }
+ }
+}
diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeMethodMap.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeMethodMap.cs
new file mode 100644
index 00000000000..1e40d549294
--- /dev/null
+++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CodeMethodMap.cs
@@ -0,0 +1,183 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.CodeDom;
+
+namespace System.ComponentModel.Design.Serialization
+{
+ ///
+ /// This structure is used by IntegrateStatements to put statements in the right place.
+ ///
+ internal class CodeMethodMap
+ {
+ private CodeStatementCollection _container;
+ private CodeStatementCollection _begin;
+ private CodeStatementCollection _end;
+ private CodeStatementCollection _statements;
+ private CodeStatementCollection _locals;
+ private CodeStatementCollection _fields;
+ private CodeStatementCollection _variables;
+ private readonly CodeStatementCollection _targetStatements;
+ private readonly CodeMemberMethod _method;
+
+ internal CodeMethodMap(CodeMemberMethod method) : this(null, method)
+ {
+ }
+
+ internal CodeMethodMap(CodeStatementCollection targetStatements, CodeMemberMethod method)
+ {
+ _method = method;
+ if (targetStatements != null)
+ {
+ _targetStatements = targetStatements;
+ }
+ else
+ {
+ _targetStatements = _method.Statements;
+ }
+ }
+
+ internal CodeStatementCollection BeginStatements
+ {
+ get
+ {
+ if (_begin == null)
+ _begin = new CodeStatementCollection();
+ return _begin;
+ }
+ }
+
+ internal CodeStatementCollection EndStatements
+ {
+ get
+ {
+ if (_end == null)
+ _end = new CodeStatementCollection();
+ return _end;
+ }
+ }
+
+ internal CodeStatementCollection ContainerStatements
+ {
+ get
+ {
+ if (_container == null)
+ _container = new CodeStatementCollection();
+ return _container;
+ }
+ }
+
+ internal CodeMemberMethod Method
+ {
+ get => _method;
+ }
+
+ internal CodeStatementCollection Statements
+ {
+ get
+ {
+ if (_statements == null)
+ _statements = new CodeStatementCollection();
+ return _statements;
+ }
+ }
+
+ internal CodeStatementCollection LocalVariables
+ {
+ get
+ {
+ if (_locals == null)
+ _locals = new CodeStatementCollection();
+ return _locals;
+ }
+ }
+
+ internal CodeStatementCollection FieldAssignments
+ {
+ get
+ {
+ if (_fields == null)
+ _fields = new CodeStatementCollection();
+ return _fields;
+ }
+ }
+
+ //TODO: Should we update RootCodeDomSerializer as well?
+ internal CodeStatementCollection VariableAssignments
+ {
+ get
+ {
+ if (_variables == null)
+ _variables = new CodeStatementCollection();
+ return _variables;
+ }
+ }
+
+ internal void Add(CodeStatementCollection statements)
+ {
+ foreach (CodeStatement statement in statements)
+ {
+ if (statement.UserData["IContainer"] is string isContainer && isContainer == "IContainer")
+ {
+ ContainerStatements.Add(statement);
+ }
+ else if (statement is CodeAssignStatement && ((CodeAssignStatement)statement).Left is CodeFieldReferenceExpression)
+ {
+ FieldAssignments.Add(statement);
+ }
+ else if (statement is CodeAssignStatement && ((CodeAssignStatement)statement).Left is CodeVariableReferenceExpression)
+ {
+ VariableAssignments.Add(statement);
+ }
+ else if (statement is CodeVariableDeclarationStatement)
+ {
+ LocalVariables.Add(statement);
+ }
+ else
+ {
+ if (statement.UserData["statement-ordering"] is string order)
+ {
+ switch (order)
+ {
+ case "begin":
+ BeginStatements.Add(statement);
+ break;
+
+ case "end":
+ EndStatements.Add(statement);
+ break;
+
+ case "default":
+ default:
+ Statements.Add(statement);
+ break;
+ }
+ }
+ else
+ {
+ Statements.Add(statement);
+ }
+ }
+ }
+ }
+
+ internal void Combine()
+ {
+ if (_container != null)
+ _targetStatements.AddRange(_container);
+ if (_locals != null)
+ _targetStatements.AddRange(_locals);
+ if (_fields != null)
+ _targetStatements.AddRange(_fields);
+ if (_variables != null)
+ _targetStatements.AddRange(_variables);
+ if (_begin != null)
+ _targetStatements.AddRange(_begin);
+ if (_statements != null)
+ _targetStatements.AddRange(_statements);
+ if (_end != null)
+ _targetStatements.AddRange(_end);
+ }
+ }
+}
diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CollectionCodeDomSerializer.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CollectionCodeDomSerializer.cs
new file mode 100644
index 00000000000..f530fc8ffa0
--- /dev/null
+++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/CollectionCodeDomSerializer.cs
@@ -0,0 +1,711 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.CodeDom;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.Globalization;
+using System.Reflection;
+
+namespace System.ComponentModel.Design.Serialization
+{
+ ///
+ /// This serializer serializes collections. This can either create statements or expressions. It will create an expression and assign it to the statement in the current context stack if the object is an array. If it is a collection with an add range or similar method, it will create a statement calling the method.
+ ///
+ public class CollectionCodeDomSerializer : CodeDomSerializer
+ {
+ private static CollectionCodeDomSerializer s_defaultSerializer;
+
+ ///
+ /// Retrieves a default static instance of this serializer.
+ ///
+ internal static CollectionCodeDomSerializer GetDefault()
+ {
+ if (s_defaultSerializer == null)
+ {
+ s_defaultSerializer = new CollectionCodeDomSerializer();
+ }
+ return s_defaultSerializer;
+ }
+
+ ///
+ /// Computes the delta between an existing collection and a modified one. This is for the case of inherited items that have collection properties so we only generate Add/AddRange calls for the items that have been added. It works by Hashing up the items in the original collection and then walking the modified collection and only returning those items which do not exist in the base collection.
+ ///
+ private ICollection GetCollectionDelta(ICollection original, ICollection modified)
+ {
+
+ if (original == null || modified == null || original.Count == 0)
+ {
+ return modified;
+ }
+
+ IEnumerator modifiedEnum = modified.GetEnumerator();
+ if (modifiedEnum == null)
+ {
+ Debug.Fail("Collection of type " + modified.GetType().FullName + " doesn't return an enumerator");
+ return modified;
+ }
+ // first hash up the values so we can quickly decide if it's a new one or not
+ IDictionary originalValues = new HybridDictionary();
+ foreach (object originalValue in original)
+ {
+ // the array could contain multiple copies of the same value (think of a string collection), so we need to be sensitive of that.
+ if (originalValues.Contains(originalValue))
+ {
+ int count = (int)originalValues[originalValue];
+ originalValues[originalValue] = ++count;
+ }
+ else
+ {
+ originalValues.Add(originalValue, 1);
+ }
+ }
+
+ // now walk through and delete existing values
+ ArrayList result = null;
+ // now compute the delta.
+ for (int i = 0; i < modified.Count && modifiedEnum.MoveNext(); i++)
+ {
+ object value = modifiedEnum.Current;
+
+ if (originalValues.Contains(value))
+ {
+ // we've got one we need to remove, so create our array list, and push all the values we've passed into it.
+ if (result == null)
+ {
+ result = new ArrayList();
+ modifiedEnum.Reset();
+ for (int n = 0; n < i && modifiedEnum.MoveNext(); n++)
+ {
+ result.Add(modifiedEnum.Current);
+ }
+ // and finally skip the one we're on
+ modifiedEnum.MoveNext();
+ }
+ // decrement the count if we've got more than one...
+ int count = (int)originalValues[value];
+
+ if (--count == 0)
+ {
+ originalValues.Remove(value);
+ }
+ else
+ {
+ originalValues[value] = count;
+ }
+ }
+ else if (result != null)
+ {
+ // this one isn't in the old list, so add it to our result list.
+ result.Add(value);
+ }
+ // this item isn't in the list and we haven't yet created our array list so just keep on going.
+ }
+
+ if (result != null)
+ {
+ return result;
+ }
+ return modified;
+ }
+
+ ///
+ /// Checks the attributes on this method to see if they support serialization.
+ ///
+ protected bool MethodSupportsSerialization(MethodInfo method)
+ {
+ if (method == null)
+ {
+ throw new ArgumentNullException("method");
+ }
+
+ object[] attrs = method.GetCustomAttributes(typeof(DesignerSerializationVisibilityAttribute), true);
+ if (attrs.Length > 0)
+ {
+ DesignerSerializationVisibilityAttribute vis = (DesignerSerializationVisibilityAttribute)attrs[0];
+ if (vis != null && vis.Visibility == DesignerSerializationVisibility.Hidden)
+ {
+ Trace("Member {0} does not support serialization.", method.Name);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// Serializes the given object into a CodeDom object.
+ ///
+ public override object Serialize(IDesignerSerializationManager manager, object value)
+ {
+ if (manager == null)
+ {
+ throw new ArgumentNullException("manager");
+ }
+
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+ object result = null;
+ using (TraceScope("CollectionCodeDomSerializer::Serialize"))
+ {
+ // We serialize collections as follows:
+ // If the collection is an array, we write out the array.
+ // If the collection has a method called AddRange, we will call that, providing an array.
+ // If the colleciton has an Add method, we will call it repeatedly.
+ // If the collection is an IList, we will cast to IList and add to it.
+ // If the collection has no add method, but is marked with PersistContents, we will enumerate the collection and serialize each element.
+ // Check to see if there is a CodePropertyReferenceExpression on the stack. If there is, we can use it as a guide for serialization.
+ CodeExpression target;
+ if (manager.Context[typeof(ExpressionContext)] is ExpressionContext cxt && cxt.PresetValue == value && manager.Context[typeof(PropertyDescriptor)] is PropertyDescriptor prop && prop.PropertyType == cxt.ExpressionType)
+ {
+ // We only want to give out an expression target if this is our context (we find this out by comparing types above) and if the context type is not an array. If it is an array, we will just return the array create expression.
+ target = cxt.Expression;
+ Trace("Valid context and property descriptor found on context stack.");
+ }
+ else
+ {
+ // This context is either the wrong context or doesn't match the property descriptor we found.
+ target = null;
+ cxt = null;
+ prop = null;
+ Trace("No valid context. We can only serialize if this is an array.");
+ }
+ // If we have a target expression see if we can create a delta for the collection. We want to do this only if the propery the collection is associated with is inherited, and if the collection is not an array.
+ if (value is ICollection collection)
+ {
+ ICollection subset = collection;
+ Type collectionType = cxt == null ? collection.GetType() : cxt.ExpressionType;
+ bool isArray = typeof(Array).IsAssignableFrom(collectionType);
+ // If we don't have a target expression and this isn't an array, let's try to create one.
+ if (target == null && !isArray)
+ {
+ target = SerializeCreationExpression(manager, collection, out bool isComplete);
+ if (isComplete)
+ {
+ return target;
+ }
+ }
+
+ if (target != null || isArray)
+ {
+ if (prop is InheritedPropertyDescriptor inheritedDesc && !isArray)
+ {
+ subset = GetCollectionDelta(inheritedDesc.OriginalValue as ICollection, collection);
+ }
+
+ result = SerializeCollection(manager, target, collectionType, collection, subset);
+
+ // See if we should emit a clear for this collection.
+ if (target != null && ShouldClearCollection(manager, collection))
+ {
+ CodeStatementCollection resultCol = result as CodeStatementCollection;
+ // If non empty collection is being serialized, but no statements were generated, there is no need to clear.
+ if (collection.Count > 0 && (result == null || (resultCol != null && resultCol.Count == 0)))
+ {
+ return null;
+ }
+
+ if (resultCol == null)
+ {
+ resultCol = new CodeStatementCollection();
+ if (result is CodeStatement resultStmt)
+ {
+ resultCol.Add(resultStmt);
+ }
+ result = resultCol;
+ }
+
+ if (resultCol != null)
+ {
+ CodeMethodInvokeExpression clearMethod = new CodeMethodInvokeExpression(target, "Clear");
+ CodeExpressionStatement clearStmt = new CodeExpressionStatement(clearMethod);
+ resultCol.Insert(0, clearStmt);
+ }
+ }
+ }
+ }
+ else
+ {
+ Debug.Fail("Collection serializer invoked for non-collection: " + (value == null ? "(null)" : value.GetType().Name));
+ TraceError("Collection serializer invoked for non collection: {0}", (value == null ? "(null)" : value.GetType().Name));
+ }
+ }
+ return result;
+ }
+
+ ///
+ /// Given a set of methods and objects, determines the method with the correct of parameter type for all objects.
+ ///
+ private static MethodInfo ChooseMethodByType(TypeDescriptionProvider provider, List methods, ICollection values)
+ {
+ // Note that this method uses reflection types which may not be compatible with runtime types. objType must be obtained from the same provider as the methods were to ensure that the reflection types all belong to the same type universe.
+ MethodInfo final = null;
+ Type finalType = null;
+ foreach (object obj in values)
+ {
+ Type objType = provider.GetReflectionType(obj);
+ MethodInfo candidate = null;
+ Type candidateType = null;
+ if (final == null || (finalType != null && !finalType.IsAssignableFrom(objType)))
+ {
+ foreach (MethodInfo method in methods)
+ {
+ ParameterInfo parameter = method.GetParameters()[0];
+ if (parameter != null)
+ {
+ Type type = parameter.ParameterType.IsArray ? parameter.ParameterType.GetElementType() : parameter.ParameterType;
+ if (type != null && type.IsAssignableFrom(objType))
+ {
+ if (final != null)
+ {
+ if (type.IsAssignableFrom(finalType))
+ {
+ final = method;
+ finalType = type;
+ break;
+ }
+ }
+ else
+ {
+ if (candidate == null)
+ {
+ candidate = method;
+ candidateType = type;
+ }
+ else
+ {
+ // we found another method. Pick the one that uses the most derived type.
+ Debug.Assert(candidateType.IsAssignableFrom(type) || type.IsAssignableFrom(candidateType), "These two types are not related. how were they chosen based on the base type");
+ bool assignable = candidateType.IsAssignableFrom(type);
+ candidate = assignable ? method : candidate;
+ candidateType = assignable ? type : candidateType;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (final == null)
+ {
+ final = candidate;
+ finalType = candidateType;
+ }
+ }
+ return final;
+ }
+
+ ///
+ /// Serializes the given collection. targetExpression will refer to the expression used to rever to the collection, but it can be null.
+ ///
+ protected virtual object SerializeCollection(IDesignerSerializationManager manager, CodeExpression targetExpression, Type targetType, ICollection originalCollection, ICollection valuesToSerialize)
+ {
+ if (manager == null) throw new ArgumentNullException("manager");
+ if (targetType == null) throw new ArgumentNullException("targetType");
+ if (originalCollection == null) throw new ArgumentNullException("originalCollection");
+ if (valuesToSerialize == null) throw new ArgumentNullException("valuesToSerialize");
+
+ object result = null;
+ bool serialized = false;
+ if (typeof(Array).IsAssignableFrom(targetType))
+ {
+ Trace("Collection is array");
+ CodeArrayCreateExpression arrayCreate = SerializeArray(manager, targetType, originalCollection, valuesToSerialize);
+ if (arrayCreate != null)
+ {
+ if (targetExpression != null)
+ {
+ result = new CodeAssignStatement(targetExpression, arrayCreate);
+ }
+ else
+ {
+ result = arrayCreate;
+ }
+ serialized = true;
+ }
+ }
+ else if (valuesToSerialize.Count > 0)
+ {
+ Trace("Searching for AddRange or Add");
+ // Use the TargetFrameworkProviderService to create a provider, or use the default for the collection if the service is not available. Since TargetFrameworkProvider reflection types are not compatible with RuntimeTypes, they can only be used with other reflection types from the same provider.
+ TypeDescriptionProvider provider = GetTargetFrameworkProvider(manager, originalCollection);
+ if (provider == null)
+ {
+ provider = TypeDescriptor.GetProvider(originalCollection);
+ }
+ MethodInfo[] methods = provider.GetReflectionType(originalCollection).GetMethods(BindingFlags.Public | BindingFlags.Instance);
+ ParameterInfo[] parameters;
+ List addRangeMethods = new List();
+ List addMethods = new List();
+ foreach (MethodInfo method in methods)
+ {
+ if (method.Name.Equals("AddRange"))
+ {
+ parameters = method.GetParameters();
+ if (parameters.Length == 1 && parameters[0].ParameterType.IsArray)
+ {
+ if (MethodSupportsSerialization(method))
+ {
+ addRangeMethods.Add(method);
+ }
+ }
+ }
+
+ if (method.Name.Equals("Add"))
+ {
+ parameters = method.GetParameters();
+ if (parameters.Length == 1)
+ {
+ if (MethodSupportsSerialization(method))
+ {
+ addMethods.Add(method);
+ }
+ }
+ }
+ }
+
+ MethodInfo addRangeMethodToUse = ChooseMethodByType(provider, addRangeMethods, valuesToSerialize);
+ if (addRangeMethodToUse != null)
+ {
+ Type elementType = provider.GetRuntimeType(addRangeMethodToUse.GetParameters()[0].ParameterType.GetElementType());
+ result = SerializeViaAddRange(manager, targetExpression, targetType, elementType, valuesToSerialize);
+ serialized = true;
+ }
+ else
+ {
+ MethodInfo addMethodToUse = ChooseMethodByType(provider, addMethods, valuesToSerialize);
+ if (addMethodToUse != null)
+ {
+ Type elementType = provider.GetRuntimeType(addMethodToUse.GetParameters()[0].ParameterType);
+ result = SerializeViaAdd(manager, targetExpression, targetType, elementType, valuesToSerialize);
+ serialized = true;
+ }
+ }
+
+ if (!serialized && originalCollection.GetType().IsSerializable)
+ {
+ result = SerializeToResourceExpression(manager, originalCollection, false);
+ }
+ }
+ else
+ {
+ Trace("Collection has no values to serialize.");
+ }
+
+ return result;
+ }
+
+ ///
+ /// Serializes the given array.
+ ///
+ private CodeArrayCreateExpression SerializeArray(IDesignerSerializationManager manager, Type targetType, ICollection array, ICollection valuesToSerialize)
+ {
+ CodeArrayCreateExpression result = null;
+ using (TraceScope("CollectionCodeDomSerializer::SerializeArray"))
+ {
+ if (((Array)array).Rank != 1)
+ {
+ TraceError("Cannot serialize arrays with rank > 1.");
+ manager.ReportError(string.Format(SR.SerializerInvalidArrayRank, ((Array)array).Rank.ToString(CultureInfo.InvariantCulture)));
+ }
+ else
+ {
+ // For an array, we need an array create expression. First, get the array type
+ Type elementType = targetType.GetElementType();
+ CodeTypeReference elementTypeRef = new CodeTypeReference(elementType);
+ Trace("Array type: {0}", elementType.Name);
+ Trace("Count: {0}", valuesToSerialize.Count);
+ // Now create an ArrayCreateExpression, and fill its initializers.
+ CodeArrayCreateExpression arrayCreate = new CodeArrayCreateExpression
+ {
+ CreateType = elementTypeRef
+ };
+ bool arrayOk = true;
+ foreach (object o in valuesToSerialize)
+ {
+ // If this object is being privately inherited, it cannot be inside this collection. Since we're writing an entire array here, we cannot write any of it.
+ if (o is IComponent && TypeDescriptor.GetAttributes(o).Contains(InheritanceAttribute.InheritedReadOnly))
+ {
+ arrayOk = false;
+ break;
+ }
+
+ CodeExpression expression = null;
+ // If there is an expression context on the stack at this point, we need to fix up the ExpressionType on it to be the array element type.
+ ExpressionContext newCxt = null;
+ if (manager.Context[typeof(ExpressionContext)] is ExpressionContext cxt)
+ {
+ newCxt = new ExpressionContext(cxt.Expression, elementType, cxt.Owner);
+ manager.Context.Push(newCxt);
+ }
+
+ try
+ {
+ expression = SerializeToExpression(manager, o);
+ }
+ finally
+ {
+ if (newCxt != null)
+ {
+ Debug.Assert(manager.Context.Current == newCxt, "Context stack corrupted.");
+ manager.Context.Pop();
+ }
+ }
+
+ if (expression is CodeExpression)
+ {
+ if (o != null && o.GetType() != elementType)
+ {
+ expression = new CodeCastExpression(elementType, expression);
+ }
+
+ arrayCreate.Initializers.Add((CodeExpression)expression);
+ }
+ else
+ {
+ arrayOk = false;
+ break;
+ }
+ }
+
+ if (arrayOk)
+ {
+ result = arrayCreate;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ ///
+ /// Serializes the given collection by creating multiple calls to an Add method.
+ ///
+ private object SerializeViaAdd(
+ IDesignerSerializationManager manager,
+ CodeExpression targetExpression,
+ Type targetType,
+ Type elementType,
+ ICollection valuesToSerialize)
+ {
+ CodeStatementCollection statements = new CodeStatementCollection();
+ using (TraceScope("CollectionCodeDomSerializer::SerializeViaAdd"))
+ {
+ Trace("Elements: {0}", valuesToSerialize.Count.ToString(CultureInfo.InvariantCulture));
+ // Here we need to invoke Add once for each and every item in the collection. We can re-use the property reference and method reference, but we will need to recreate the invoke statement each time.
+ CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression(targetExpression, "Add");
+
+ if (valuesToSerialize.Count > 0)
+ {
+ foreach (object o in valuesToSerialize)
+ {
+ // If this object is being privately inherited, it cannot be inside this collection.
+ bool genCode = !(o is IComponent);
+ if (!genCode)
+ {
+ InheritanceAttribute ia = (InheritanceAttribute)TypeDescriptor.GetAttributes(o)[typeof(InheritanceAttribute)];
+ if (ia != null)
+ {
+ if (ia.InheritanceLevel == InheritanceLevel.InheritedReadOnly)
+ genCode = false;
+ else
+ genCode = true;
+ }
+ else
+ {
+ genCode = true;
+ }
+ }
+
+ Debug.Assert(genCode, "Why didn't GetCollectionDelta calculate the same thing?");
+ if (genCode)
+ {
+ CodeMethodInvokeExpression statement = new CodeMethodInvokeExpression
+ {
+ Method = methodRef
+ };
+ CodeExpression serializedObj = null;
+
+ // If there is an expression context on the stack at this point,
+ // we need to fix up the ExpressionType on it to be the element type.
+ ExpressionContext newCxt = null;
+
+ if (manager.Context[typeof(ExpressionContext)] is ExpressionContext cxt)
+ {
+ newCxt = new ExpressionContext(cxt.Expression, elementType, cxt.Owner);
+ manager.Context.Push(newCxt);
+ }
+
+ try
+ {
+ serializedObj = SerializeToExpression(manager, o);
+ }
+ finally
+ {
+ if (newCxt != null)
+ {
+ Debug.Assert(manager.Context.Current == newCxt, "Context stack corrupted.");
+ manager.Context.Pop();
+ }
+ }
+
+ if (o != null && !elementType.IsAssignableFrom(o.GetType()) && o.GetType().IsPrimitive)
+ {
+ serializedObj = new CodeCastExpression(elementType, serializedObj);
+ }
+
+ if (serializedObj != null)
+ {
+ statement.Parameters.Add(serializedObj);
+ statements.Add(statement);
+ }
+ }
+ }
+ }
+ }
+ return statements;
+ }
+
+ ///
+ /// Serializes the given collection by creating an array and passing it to the AddRange method.
+ ///
+ private object SerializeViaAddRange(
+ IDesignerSerializationManager manager,
+ CodeExpression targetExpression,
+ Type targetType,
+ Type elementType,
+ ICollection valuesToSerialize)
+ {
+ CodeStatementCollection statements = new CodeStatementCollection();
+ using (TraceScope("CollectionCodeDomSerializer::SerializeViaAddRange"))
+ {
+ Trace("Elements: {0}", valuesToSerialize.Count.ToString(CultureInfo.InvariantCulture));
+
+ if (valuesToSerialize.Count > 0)
+ {
+ ArrayList arrayList = new ArrayList(valuesToSerialize.Count);
+ foreach (object o in valuesToSerialize)
+ {
+ // If this object is being privately inherited, it cannot be inside this collection.
+ bool genCode = !(o is IComponent);
+ if (!genCode)
+ {
+ InheritanceAttribute ia = (InheritanceAttribute)TypeDescriptor.GetAttributes(o)[typeof(InheritanceAttribute)];
+
+ if (ia != null)
+ {
+ if (ia.InheritanceLevel == InheritanceLevel.InheritedReadOnly)
+ genCode = false;
+ else
+ genCode = true;
+ }
+ else
+ {
+ genCode = true;
+ }
+ }
+
+ Debug.Assert(genCode, "Why didn't GetCollectionDelta calculate the same thing?");
+ if (genCode)
+ {
+ CodeExpression exp = null;
+ // If there is an expression context on the stack at this point, we need to fix up the ExpressionType on it to be the element type.
+ ExpressionContext newCxt = null;
+
+ if (manager.Context[typeof(ExpressionContext)] is ExpressionContext cxt)
+ {
+ newCxt = new ExpressionContext(cxt.Expression, elementType, cxt.Owner);
+ manager.Context.Push(newCxt);
+ }
+
+ try
+ {
+ exp = SerializeToExpression(manager, o);
+ }
+ finally
+ {
+ if (newCxt != null)
+ {
+ Debug.Assert(manager.Context.Current == newCxt, "Context stack corrupted.");
+ manager.Context.Pop();
+ }
+ }
+
+ if (exp != null)
+ {
+ // Check to see if we need a cast
+ if (o != null && !elementType.IsAssignableFrom(o.GetType()))
+ {
+ exp = new CodeCastExpression(elementType, exp);
+ }
+ arrayList.Add(exp);
+ }
+ }
+ }
+
+ if (arrayList.Count > 0)
+ {
+ // Now convert the array list into an array create expression.
+ CodeTypeReference elementTypeRef = new CodeTypeReference(elementType);
+ // Now create an ArrayCreateExpression, and fill its initializers.
+ CodeArrayCreateExpression arrayCreate = new CodeArrayCreateExpression
+ {
+ CreateType = elementTypeRef
+ };
+ foreach (CodeExpression exp in arrayList)
+ {
+ arrayCreate.Initializers.Add(exp);
+ }
+
+ CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression(targetExpression, "AddRange");
+ CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression
+ {
+ Method = methodRef
+ };
+ methodInvoke.Parameters.Add(arrayCreate);
+ statements.Add(new CodeExpressionStatement(methodInvoke));
+ }
+ }
+ }
+ return statements;
+ }
+
+ ///
+ /// Returns true if we should clear the collection contents.
+ ///
+ private bool ShouldClearCollection(IDesignerSerializationManager manager, ICollection collection)
+ {
+ bool shouldClear = false;
+ PropertyDescriptor clearProp = manager.Properties["ClearCollections"];
+ if (clearProp != null && clearProp.PropertyType == typeof(bool) && ((bool)clearProp.GetValue(manager) == true))
+ {
+ shouldClear = true;
+ }
+
+ if (!shouldClear)
+ {
+ SerializeAbsoluteContext absolute = (SerializeAbsoluteContext)manager.Context[typeof(SerializeAbsoluteContext)];
+ PropertyDescriptor prop = manager.Context[typeof(PropertyDescriptor)] as PropertyDescriptor;
+ if (absolute != null && absolute.ShouldSerialize(prop))
+ {
+ shouldClear = true;
+ }
+ }
+
+ if (shouldClear)
+ {
+ MethodInfo clearMethod = TypeDescriptor.GetReflectionType(collection).GetMethod("Clear", BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null);
+ if (clearMethod == null || !MethodSupportsSerialization(clearMethod))
+ {
+ shouldClear = false;
+ }
+ }
+ return shouldClear;
+ }
+ }
+}
diff --git a/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCache.cs b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCache.cs
new file mode 100644
index 00000000000..254d746654a
--- /dev/null
+++ b/src/System.Windows.Forms.Design/src/System/ComponentModel/Design/Serialization/ComponentCache.cs
@@ -0,0 +1,353 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.CodeDom;
+using System.Collections.Generic;
+
+namespace System.ComponentModel.Design.Serialization
+{
+ ///
+ /// This class is used to cache serialized properties and events of components to speed-up Design to Code view switches
+ ///
+ internal class ComponentCache : IDisposable
+ {
+ private Dictionary