当前位置:  开发笔记 > 编程语言 > 正文

我可以序列化C#Type对象吗?

如何解决《我可以序列化C#Type对象吗?》经验,为你挑选了3个好方法。

我正在尝试以下列方式序列化Type对象:

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

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

"不期望使用System.Text.StringBuilder类型.使用XmlInclude或SoapInclude属性指定静态未知的类型."

有没有办法让我序列化Type对象?请注意,我不是要尝试序列化StringBuilder自身,而是Type包含有关StringBuilder类的元数据的对象.



1> Brian Sulliv..:

我不知道只能使用包含完全限定名称的字符串创建Type对象.要获取完全限定名称,可以使用以下命令:

string typeName = typeof (StringBuilder).FullName;

然后,您可以根据需要保留此字符串,然后重建类型如下:

Type t = Type.GetType(typeName);

如果需要创建该类型的实例,可以执行以下操作:

object o = Activator.CreateInstance(t);

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


解决方案是使用AssemblyQualifiedName而不是FullName
警告Type.GetType(typeName); 仅适用于与调用相同的程序集中的类型.
对于泛型类型,Type.GetType()将失败.

2> hypehuman..:

我有同样的问题,我的解决方案是创建一个SerializableType类.它可以自由地转换为System.Type和从System.Type转换,但它序列化为字符串.您所要做的就是将变量声明为SerializableType,从那时起您可以将其称为System.Type.

这是班级:

// 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 _bees;

    ...

    public B GetB(Type type)
    {
        return _bees[type];
    }

    ...

}

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



3> Dzyann..:

如果类型与调用在同一个程序集中(如其中一条注释中指出的GreyCloud),Brian的答案很有效.因此,如果类型在另一个程序集中,则需要使用AssemblyQualifiedName,因为GreyCloud也指出了这一点.

但是,由于AssemblyQualifiedName保存了版本,如果程序集的版本与您拥有该类型的字符串中的版本不同,则它将不起作用.

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

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;
    }

我发布这个以防任何人需要它.

推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有