我可以序列化一个C#types的对象吗?

我试图按以下方式序列化一个Type对象:

Type myType = typeof (StringBuilder); var serializer = new XmlSerializer(typeof(Type)); TextWriter writer = new StringWriter(); serializer.Serialize(writer, myType); 

当我这样做时,对Serialize的调用引发以下exception:

“typesSystem.Text.StringBuilder不是预期的,请使用XmlInclude或SoapInclude属性指定静态未知的types。

有没有一种方法可以序列化Type对象? 请注意,我不是试图序列化StringBuilder本身,而是包含有关StringBuilder类的元数据的Type对象。

我不知道只能使用包含完全限定名称的string来创buildType对象。 要获取完全限定名称,可以使用以下命令:

 string typeName = typeof (StringBuilder).FullName; 

然后你可以坚持这个string,然后重新构build这样的types:

 Type t = Type.GetType(typeName); 

如果你需要创build一个types的实例,你可以这样做:

 object o = Activator.CreateInstance(t); 

如果你检查o.GetType()的值,它将是StringBuilder,就像你所期望的一样。

我有同样的问题,我的解决scheme是创build一个SerializableType类。 它自由地转换为System.Type或从System.Type转换,但它作为一个string序列化。 你所要做的就是把这个variables声明为一个SerializableType,然后你可以把它作为System.Type来引用。

这是class级:

 // a version of System.Type that can be serialized [DataContract] public class SerializableType { public Type type; // when serializing, store as a string [DataMember] string TypeString { get { if (type == null) return null; return type.FullName; } set { if (value == null) type = null; else { type = Type.GetType(value); } } } // constructors public SerializableType() { type = null; } public SerializableType(Type t) { type = t; } // allow SerializableType to implicitly be converted to and from System.Type static public implicit operator Type(SerializableType stype) { return stype.type; } static public implicit operator SerializableType(Type t) { return new SerializableType(t); } // overload the == and != operators public static bool operator ==(SerializableType a, SerializableType b) { // If both are null, or both are same instance, return true. if (System.Object.ReferenceEquals(a, b)) { return true; } // If one is null, but not both, return false. if (((object)a == null) || ((object)b == null)) { return false; } // Return true if the fields match: return a.type == b.type; } public static bool operator !=(SerializableType a, SerializableType b) { return !(a == b); } // we don't need to overload operators between SerializableType and System.Type because we already enabled them to implicitly convert public override int GetHashCode() { return type.GetHashCode(); } // overload the .Equals method public override bool Equals(System.Object obj) { // If parameter is null return false. if (obj == null) { return false; } // If parameter cannot be cast to SerializableType return false. SerializableType p = obj as SerializableType; if ((System.Object)p == null) { return false; } // Return true if the fields match: return (type == p.type); } public bool Equals(SerializableType p) { // If parameter is null return false: if ((object)p == null) { return false; } // Return true if the fields match: return (type == p.type); } } 

和一个用法的例子:

 [DataContract] public class A { ... [DataMember] private Dictionary<SerializableType, B> _bees; ... public B GetB(Type type) { return _bees[type]; } ... } 

您也可以考虑使用AssemblyQualifiedName而不是Type.FullName – 请参阅@GreyCloud的评论

如果types与调用的程序集相同(如GreyCloud在其中一个注释中指出的那样), Brian的答案会很有效。 因此,如果types在另一个程序集中,则需要使用AssemblyQualifiedName作为GreyCloud也指出的。

但是,由于AssemblyQualifiedName保存版本,如果您的程序集具有与string中的types不同的版本,它将不起作用。

在我的情况下,这是一个问题,我解决了这样的问题:

 string typeName = typeof (MyClass).FullName; Type type = GetTypeFrom(typeName); object myInstance = Activator.CreateInstance(type); 

GetTypeFrom方法

 private Type GetTypeFrom(string valueType) { var type = Type.GetType(valueType); if (type != null) return type; try { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); //To speed things up, we check first in the already loaded assemblies. foreach (var assembly in assemblies) { type = assembly.GetType(valueType); if (type != null) break; } if (type != null) return type; var loadedAssemblies = assemblies.ToList(); foreach (var loadedAssembly in assemblies) { foreach (AssemblyName referencedAssemblyName in loadedAssembly.GetReferencedAssemblies()) { var found = loadedAssemblies.All(x => x.GetName() != referencedAssemblyName); if (!found) { try { var referencedAssembly = Assembly.Load(referencedAssemblyName); type = referencedAssembly.GetType(valueType); if (type != null) break; loadedAssemblies.Add(referencedAssembly); } catch { //We will ignore this, because the Type might still be in one of the other Assemblies. } } } } } catch(Exception exception) { //throw my custom exception } if (type == null) { //throw my custom exception. } return type; } 

我张贴这个以防万一需要它。

根据System.Type [1]的MSDN文档,您应该能够序列化System.Type对象。 但是,由于错误是明确指向System.Text.StringBuilder,这可能是导致序列化错误的类。

[1]types类(系统) – http://msdn.microsoft.com/en-us/library/system.type.aspx

只是看了它的定义,它没有标记为Serializable。 如果您确实需要将这些数据序列化,那么您可能必须将其转换为标记为这样的自定义类。

 public abstract class Type : System.Reflection.MemberInfo Member of System Summary: Represents type declarations: class types, interface types, array types, value types, enumeration types, type parameters, generic type definitions, and open or closed constructed generic types. Attributes: [System.Runtime.InteropServices.ClassInterfaceAttribute(0), System.Runtime.InteropServices.ComDefaultInterfaceAttribute(System.Runtime.InteropServices._Type), System.Runtime.InteropServices.ComVisibleAttribute(true)]