The Labs \ Source Viewer \ SSCLI \ System.ComponentModel \ NullableConverter

  1. //------------------------------------------------------------------------------
  2. // <copyright file="NullableConverter.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.ComponentModel
  16. {
  17.     using System.Collections;
  18.     using System.ComponentModel.Design.Serialization;
  19.     using System.Diagnostics;
  20.     using System.Globalization;
  21.     using System.Reflection;
  22.     using System.Runtime.InteropServices;
  23.     using System.Runtime.Remoting;
  24.     using System.Runtime.Serialization.Formatters;
  25.     using System.Security.Permissions;
  26.    
  27.     /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter"]/*' />
  28.     /// <devdoc>
  29.     /// </devdoc>
  30.     [HostProtection(SharedState = true)]
  31.     public class NullableConverter : TypeConverter
  32.     {
  33.         Type nullableType;
  34.         Type simpleType;
  35.         TypeConverter simpleTypeConverter;
  36.        
  37.         /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter.NullableConverter"]/*' />
  38.         /// <devdoc>
  39.         /// </devdoc>
  40.         public NullableConverter(Type type)
  41.         {
  42.             this.nullableType = type;
  43.            
  44.             this.simpleType = Nullable.GetUnderlyingType(type);
  45.             if (this.simpleType == null) {
  46.                 throw new ArgumentException(SR.GetString(SR.NullableConverterBadCtorArg), "type");
  47.             }
  48.            
  49.             this.simpleTypeConverter = TypeDescriptor.GetConverter(this.simpleType);
  50.         }
  51.        
  52.         /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter.CanConvertFrom"]/*' />
  53.         /// <devdoc>
  54.         /// </devdoc>
  55.         public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
  56.         {
  57.             if (sourceType == this.simpleType) {
  58.                 return true;
  59.             }
  60.             else if (this.simpleTypeConverter != null) {
  61.                 return this.simpleTypeConverter.CanConvertFrom(context, sourceType);
  62.             }
  63.             else {
  64.                 return base.CanConvertFrom(context, sourceType);
  65.             }
  66.         }
  67.        
  68.         /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter.ConvertFrom"]/*' />
  69.         /// <devdoc>
  70.         /// </devdoc>
  71.         public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
  72.         {
  73.             if (value == null || value.GetType() == this.simpleType) {
  74.                 return value;
  75.             }
  76.             else if (value is string && String.IsNullOrEmpty(value as string)) {
  77.                 return null;
  78.             }
  79.             else if (this.simpleTypeConverter != null) {
  80.                 object convertedValue = this.simpleTypeConverter.ConvertFrom(context, culture, value);
  81.                 return convertedValue;
  82.             }
  83.             else {
  84.                 return base.ConvertFrom(context, culture, value);
  85.             }
  86.         }
  87.        
  88.         /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter.CanConvertTo"]/*' />
  89.         /// <devdoc>
  90.         /// </devdoc>
  91.         public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
  92.         {
  93.             if (destinationType == this.simpleType) {
  94.                 return true;
  95.             }
  96.             else if (destinationType == typeof(InstanceDescriptor)) {
  97.                 return true;
  98.             }
  99.             else if (this.simpleTypeConverter != null) {
  100.                 return this.simpleTypeConverter.CanConvertTo(context, destinationType);
  101.             }
  102.             else {
  103.                 return base.CanConvertTo(context, destinationType);
  104.             }
  105.         }
  106.        
  107.         /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter.ConvertTo"]/*' />
  108.         /// <devdoc>
  109.         /// </devdoc>
  110.         public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
  111.         {
  112.             if (destinationType == null) {
  113.                 throw new ArgumentNullException("destinationType");
  114.             }
  115.            
  116.             if (destinationType == this.simpleType && this.nullableType.IsInstanceOfType(value)) {
  117.                 return value;
  118.             }
  119.             else if (destinationType == typeof(InstanceDescriptor)) {
  120.                 ConstructorInfo ci = nullableType.GetConstructor(new Type[] {simpleType});
  121.                 Debug.Assert(ci != null, "Couldn't find constructor");
  122.                 return new InstanceDescriptor(ci, new object[] {value}, true);
  123.             }
  124.             else if (value == null) {
  125.                 // Handle our own nulls here
  126.                 if (destinationType == typeof(string)) {
  127.                     return string.Empty;
  128.                 }
  129.             }
  130.             else if (this.simpleTypeConverter != null) {
  131.                 return this.simpleTypeConverter.ConvertTo(context, culture, value, destinationType);
  132.             }
  133.            
  134.             return base.ConvertTo(context, culture, value, destinationType);
  135.         }
  136.        
  137.         /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter.CreateInstance"]/*' />
  138.         /// <devdoc>
  139.         /// </devdoc>
  140.         public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)
  141.         {
  142.             if (simpleTypeConverter != null) {
  143.                 object instance = simpleTypeConverter.CreateInstance(context, propertyValues);
  144.                 return instance;
  145.             }
  146.            
  147.             return base.CreateInstance(context, propertyValues);
  148.         }
  149.        
  150.         /// <devdoc>
  151.         /// <para>Gets a value indicating whether changing a value on this object requires a
  152.         /// call to <see cref='System.ComponentModel.TypeConverter.CreateInstance'/> to create a new value,
  153.         /// using the specified context.</para>
  154.         /// </devdoc>
  155.         public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
  156.         {
  157.             if (simpleTypeConverter != null) {
  158.                 return simpleTypeConverter.GetCreateInstanceSupported(context);
  159.             }
  160.            
  161.             return base.GetCreateInstanceSupported(context);
  162.         }
  163.        
  164.         /// <devdoc>
  165.         /// <para>Gets a collection of properties for
  166.         /// the type of array specified by the value parameter using the specified context and
  167.         /// attributes.</para>
  168.         /// </devdoc>
  169.         public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
  170.         {
  171.             if (simpleTypeConverter != null) {
  172.                 object unwrappedValue = value;
  173.                 return simpleTypeConverter.GetProperties(context, unwrappedValue, attributes);
  174.             }
  175.            
  176.             return base.GetProperties(context, value, attributes);
  177.         }
  178.        
  179.         /// <devdoc>
  180.         /// <para>Gets a value indicating
  181.         /// whether this object supports properties using the
  182.         /// specified context.</para>
  183.         /// </devdoc>
  184.         public override bool GetPropertiesSupported(ITypeDescriptorContext context)
  185.         {
  186.             if (simpleTypeConverter != null) {
  187.                 return simpleTypeConverter.GetPropertiesSupported(context);
  188.             }
  189.            
  190.             return base.GetPropertiesSupported(context);
  191.         }
  192.        
  193.         /// <devdoc>
  194.         /// <para>Gets a collection of standard values for the data type this type converter is
  195.         /// designed for.</para>
  196.         /// </devdoc>
  197.         public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
  198.         {
  199.             if (simpleTypeConverter != null) {
  200.                 StandardValuesCollection values = simpleTypeConverter.GetStandardValues(context);
  201.                 if (GetStandardValuesSupported(context) && values != null) {
  202.                     // Create a set of standard values around nullable instances.
  203.                     object[] wrappedValues = new object[values.Count + 1];
  204.                     int idx = 0;
  205.                    
  206.                     wrappedValues[idx++] = null;
  207.                     foreach (object value in values) {
  208.                         wrappedValues[idx++] = value;
  209.                     }
  210.                    
  211.                     return new StandardValuesCollection(wrappedValues);
  212.                 }
  213.             }
  214.            
  215.             return base.GetStandardValues(context);
  216.         }
  217.        
  218.         /// <devdoc>
  219.         /// <para>Gets a value indicating whether the collection of standard values returned from
  220.         /// <see cref='System.ComponentModel.TypeConverter.GetStandardValues'/> is an exclusive
  221.         /// list of possible values, using the specified context.</para>
  222.         /// </devdoc>
  223.         public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
  224.         {
  225.             if (simpleTypeConverter != null) {
  226.                 return simpleTypeConverter.GetStandardValuesExclusive(context);
  227.             }
  228.            
  229.             return base.GetStandardValuesExclusive(context);
  230.         }
  231.        
  232.         /// <devdoc>
  233.         /// <para>Gets a value indicating
  234.         /// whether this object
  235.         /// supports a standard set of values that can be picked
  236.         /// from a list using the specified context.</para>
  237.         /// </devdoc>
  238.         public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
  239.         {
  240.             if (simpleTypeConverter != null) {
  241.                 return simpleTypeConverter.GetStandardValuesSupported(context);
  242.             }
  243.            
  244.             return base.GetStandardValuesSupported(context);
  245.         }
  246.        
  247.         /// <devdoc>
  248.         /// <para>Gets
  249.         /// a value indicating whether the given value object is valid for this type.</para>
  250.         /// </devdoc>
  251.         public override bool IsValid(ITypeDescriptorContext context, object value)
  252.         {
  253.             if (simpleTypeConverter != null) {
  254.                 object unwrappedValue = value;
  255.                 if (unwrappedValue == null) {
  256.                     return true;
  257.                     // null is valid for nullable.
  258.                 }
  259.                 else {
  260.                     return simpleTypeConverter.IsValid(context, unwrappedValue);
  261.                 }
  262.             }
  263.            
  264.             return base.IsValid(context, value);
  265.         }
  266.        
  267.         /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter.NullableType"]/*' />
  268.         /// <devdoc>
  269.         /// </devdoc>
  270.         public Type NullableType {
  271.             get { return nullableType; }
  272.         }
  273.        
  274.         /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter.UnderlyingType"]/*' />
  275.         /// <devdoc>
  276.         /// </devdoc>
  277.         public Type UnderlyingType {
  278.             get { return simpleType; }
  279.         }
  280.        
  281.         /// <include file='doc\NullableConverter.uex' path='docs/doc[@for="NullableConverter.UnderlyingTypeConverter"]/*' />
  282.         /// <devdoc>
  283.         /// </devdoc>
  284.         public TypeConverter UnderlyingTypeConverter {
  285.             get { return simpleTypeConverter; }
  286.         }
  287.     }
  288. }

Developer Fusion