Могу ли я сериализовать объект Type C#?
Я пытаюсь сериализовать объект Type следующим 9X_deserialize образом:
Type myType = typeof (StringBuilder); var serializer = new XmlSerializer(typeof(Type)); TextWriter writer = new StringWriter(); serializer.Serialize(writer, myType);
Когда я это делаю, вызов Serialize 9X_serialized вызывает следующее исключение:
"Тип System.Text.StringBuilder 9X_serialization не ожидался. Используйте Атрибут XmlInclude 9X_csharp или SoapInclude для указания типов, которые 9X_serialize не известны статически."
Есть ли способ 9X_serialize сериализовать объект Type
? Обратите внимание, что 9X_serialized я пытаюсь сериализовать не сам StringBuilder
, а объект 9X_unserialize Type
, содержащий метаданные о классе StringBuilder
.
- Зачем сериализовать тип? Если десериализация не является .Net, она не может ее использовать, если это так, все, что вам нужно передать, - эт ...
Ответ #1
Ответ на вопрос: Могу ли я сериализовать объект Type C#?
Я не знал, что объект Type может быть создан 9X_serialized только с помощью строки, содержащей полное 9X_serialized имя. Чтобы получить полное имя, вы можете 9X_visual-c# использовать следующее:
string typeName = typeof (StringBuilder).FullName;
Затем вы можете сохранить 9X_visual-c# эту строку при необходимости, а затем восстановить 9X_csharp тип следующим образом:
Type t = Type.GetType(typeName);
Если вам нужно создать 9X_deserialize экземпляр типа, вы можете сделать это:
object o = Activator.CreateInstance(t);
Если 9X_c#.net вы проверите значение o.GetType(), это будет 9X_serialization StringBuilder, как и следовало ожидать.
- решение состоит в том, чтобы использовать AssemblyQualifiedName вмест ...
Ответ #2
Ответ на вопрос: Могу ли я сериализовать объект Type C#?
У меня была та же проблема, и я решил создать 9X_serializer класс SerializableType. Он свободно преобразуется 9X_csharp в System.Type и из него, но сериализуется 9X_c#.net как строка. Все, что вам нужно сделать, это 9X_serialze объявить переменную как SerializableType, и 9X_.cs-file с этого момента вы можете ссылаться на нее 9X_c# как на 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]; } ... }
Вы 9X_deserialize также можете рассмотреть возможность использования 9X_csharp AssemblyQualifiedName вместо Type.FullName 9X_c-sharp - см. комментарий @GreyCloud
- +1 Кроме того, возможно, стоит переопределить `toString()` и вернуть `return this.Type? .ToString(); ...
Ответ #3
Ответ на вопрос: Могу ли я сериализовать объект Type C#?
Brian's ответ работает хорошо, если тип находится 9X_c#.net в той же сборке, что и вызов (например, GreyCloud 9X_serialization указал в одном из комментариев). Поэтому, если 9X_.cs-file тип находится в другой сборке, вам нужно 9X_csharp использовать AssemblyQualifiedName, как также указал GreyCloud.
Однако, поскольку 9X_deserialize AssemblyQualifiedName сохраняет версию, если ваши сборки имеют 9X_serialized версию, отличную от той, которая указана 9X_c#-language в строке, где у вас есть тип, это не сработает.
В 9X_deserialize моем случае это была проблема, и я решил 9X_serialization ее следующим образом:
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; }
Я публикую это на случай, если 9X_visual-c# это кому-нибудь понадобится.
Ответ #4
Ответ на вопрос: Могу ли я сериализовать объект Type C#?
В соответствии с документацией MSDN для 9X_c#.net System.Type [1] вы должны иметь возможность 9X_deserialize сериализовать объект System.Type. Однако, поскольку 9X_c#.net ошибка явно относится к System.Text.StringBuilder, вероятно, именно 9X_serialze этот класс вызывает ошибку сериализации.
[1] Тип 9X_deserialize Класс (Система) - http://msdn.microsoft.com/en-us/library/system.type.aspx
Ответ #5
Ответ на вопрос: Могу ли я сериализовать объект Type C#?
Я столкнулся с этой проблемой, пытаясь выполнить 9X_c#-language двоичную сериализацию в стандарте .net 2.0. В 9X_serialze итоге я решил проблему, используя собственные 9X_c#.net SurrogateSelector
и SerializationBinder
.
TypeSerializationBinder
был необходим, потому что у платформы 9X_serialze возникли проблемы с разрешением System.RuntimeType
до того, как 9X_c#-language она получила SurrogateSelector
. Я действительно не понимаю, почему 9X_serializer тип должен быть определен до этого шага 9X_visual-c# ...
Вот код:
// Serializes and deserializes System.Type public class TypeSerializationSurrogate : ISerializationSurrogate { public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) { info.AddValue(nameof(Type.FullName), (obj as Type).FullName); } public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) { return Type.GetType(info.GetString(nameof(Type.FullName))); } } // Just a stub, doesn't need an implementation public class TypeStub : Type { ... } // Binds "System.RuntimeType" to our TypeStub public class TypeSerializationBinder : SerializationBinder { public override Type BindToType(string assemblyName, string typeName) { if(typeName == "System.RuntimeType") { return typeof(TypeStub); } return Type.GetType($"{typeName}, {assemblyName}"); } } // Selected out TypeSerializationSurrogate when [de]serializing Type public class TypeSurrogateSelector : ISurrogateSelector { public virtual void ChainSelector(ISurrogateSelector selector) => throw new NotSupportedException(); public virtual ISurrogateSelector GetNextSelector() => throw new NotSupportedException(); public virtual ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector) { if(typeof(Type).IsAssignableFrom(type)) { selector = this; return new TypeSerializationSurrogate(); } selector = null; return null; } }
Пример использования:
byte[] bytes var serializeFormatter = new BinaryFormatter() { SurrogateSelector = new TypeSurrogateSelector() } using (var stream = new MemoryStream()) { serializeFormatter.Serialize(stream, typeof(string)); bytes = stream.ToArray(); } var deserializeFormatter = new BinaryFormatter() { SurrogateSelector = new TypeSurrogateSelector(), Binder = new TypeDeserializationBinder() } using (var stream = new MemoryStream(bytes)) { type = (Type)deserializeFormatter .Deserialize(stream); Assert.Equal(typeof(string), type); }
Ответ #6
Ответ на вопрос: Могу ли я сериализовать объект Type C#?
Только что посмотрел его определение, оно 9X_.cs-file не помечено как Serializable. Если вам действительно 9X_serialisation нужно сериализовать эти данные, возможно, вам 9X_c# придется преобразовать их в пользовательский 9X_serialisation класс, помеченный как таковой.
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)]
- Неправда, `System.Type` не сериализуем, но конкретная реализация` System.RuntimeType` есть.<p ...
-
14
-
8
-
1
-
9
-
4
-
6
-
7
-
6
-
3
-
17
-
6
-
4
-
8
-
9
-
7
-
10
-
3
-
9
-
5
-
5
-
2
-
10
-
7
-
5
-
8
-
2
-
6
-
6
-
2
-
5
-
4
-
2
-
2
-
5
-
2
-
8
-
3
-
4
-
3
-
3
-
30
-
1
-
3
-
5
-
8
-
1
-
6
-
5
-
5
-
2