C #의 개체가 직렬화 가능한지 확인하는 쉬운 방법을 찾고 있습니다.
우리가 알고 있듯이 ISerializable 인터페이스 를 구현 하거나 클래스 맨 위에 [Serializable] 을 배치하여 객체를 직렬화 할 수 있습니다.
내가 찾고있는 것은 속성을 얻기 위해 클래스를 반영하지 않고도 이것을 확인하는 빠른 방법입니다. 인터페이스는 is 문을 사용하면 빠릅니다 .
@Flard의 제안을 사용하면 이것이 내가 생각해 낸 코드이며 더 나은 방법이 있다는 비명을 지 릅니다.
private static bool IsSerializable(T obj)
{
return ((obj is ISerializable) || (Attribute.IsDefined(typeof (T), typeof (SerializableAttribute))));
}
또는 개체의 형식을 가져온 다음 형식에 IsSerializable 속성을 사용하는 것이 더 좋습니다.
typeof(T).IsSerializable
이것은 클래스에 다른 클래스가 포함되어있는 경우에만 처리하는 클래스로만 보이지만 모두 확인하거나 @pb가 지적한대로 오류를 시도하고 직렬화하고 기다릴 수 있습니다.
답변
Type
라는 클래스 에 멋진 속성이 IsSerializable
있습니다.
답변
직렬화 가능한 속성에 대해 직렬화되는 객체의 그래프에서 모든 유형을 확인해야합니다. 가장 쉬운 방법은 객체를 직렬화하고 예외를 포착하는 것입니다. (그러나 그것은 가장 깨끗한 해결책이 아닙니다). Type.IsSerializable 및 serializalbe 속성 확인은 그래프를 고려하지 않습니다.
견본
[Serializable]
public class A
{
public B B = new B();
}
public class B
{
public string a = "b";
}
[Serializable]
public class C
{
public D D = new D();
}
[Serializable]
public class D
{
public string d = "D";
}
class Program
{
static void Main(string[] args)
{
var a = typeof(A);
var aa = new A();
Console.WriteLine("A: {0}", a.IsSerializable); // true (WRONG!)
var c = typeof(C);
Console.WriteLine("C: {0}", c.IsSerializable); //true
var form = new BinaryFormatter();
// throws
form.Serialize(new MemoryStream(), aa);
}
}
답변
이것은 .NET 3.5 이상에 대해 업데이트해야 할 수있는 오래된 질문입니다. Type.IsSerializable은 클래스가 DataContract 특성을 사용하는 경우 실제로 false를 반환 할 수 있습니다. 다음은 내가 사용하는 스 니펫입니다. 냄새가 나면 알려주세요. 🙂
public static bool IsSerializable(this object obj)
{
Type t = obj.GetType();
return Attribute.IsDefined(t, typeof(DataContractAttribute)) || t.IsSerializable || (obj is IXmlSerializable)
}
답변
다른 사람들이 지적한대로 Type.IsSerializable을 사용하십시오.
개체 그래프의 모든 멤버가 직렬화 가능한지 여부를 반영하고 확인하는 것은 가치가 없을 것입니다.
멤버는 직렬화 가능 유형으로 선언 될 수 있지만 실제로 다음 인위적인 예제에서와 같이 직렬화 가능하지 않은 파생 된 유형으로 인스턴스화됩니다.
[Serializable]
public class MyClass
{
public Exception TheException; // serializable
}
public class MyNonSerializableException : Exception
{
...
}
...
MyClass myClass = new MyClass();
myClass.TheException = new MyNonSerializableException();
// myClass now has a non-serializable member
따라서 유형의 특정 인스턴스가 직렬화 가능하다고 판단하더라도 일반적으로 이것이 모든 인스턴스에 해당되는지 확신 할 수 없습니다.
답변
Attribute.IsDefined(typeof (YourClass), typeof (SerializableAttribute));
아마도 수중 반사를 포함하지만 가장 간단한 방법은 무엇입니까?
답변
확장 메서드를 사용하여 모든 클래스에서 사용할 수 있도록하는 3.5 변형이 있습니다.
public static bool IsSerializable(this object obj)
{
if (obj is ISerializable)
return true;
return Attribute.IsDefined(obj.GetType(), typeof(SerializableAttribute));
}
답변
이 질문에 대한 대답 과 여기 에 대답 을 가져 와서 직렬화 할 수없는 유형 목록을 얻도록 수정했습니다. 이렇게하면 표시 할 항목을 쉽게 알 수 있습니다.
private static void NonSerializableTypesOfParentType(Type type, List<string> nonSerializableTypes)
{
// base case
if (type.IsValueType || type == typeof(string)) return;
if (!IsSerializable(type))
nonSerializableTypes.Add(type.Name);
foreach (var propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
if (propertyInfo.PropertyType.IsGenericType)
{
foreach (var genericArgument in propertyInfo.PropertyType.GetGenericArguments())
{
if (genericArgument == type) continue; // base case for circularly referenced properties
NonSerializableTypesOfParentType(genericArgument, nonSerializableTypes);
}
}
else if (propertyInfo.GetType() != type) // base case for circularly referenced properties
NonSerializableTypesOfParentType(propertyInfo.PropertyType, nonSerializableTypes);
}
}
private static bool IsSerializable(Type type)
{
return (Attribute.IsDefined(type, typeof(SerializableAttribute)));
//return ((type is ISerializable) || (Attribute.IsDefined(type, typeof(SerializableAttribute))));
}
그리고 당신은 그것을 …
List<string> nonSerializableTypes = new List<string>();
NonSerializableTypesOfParentType(aType, nonSerializableTypes);
실행되면 nonSerializableTypes에 목록이 있습니다. 빈 목록을 재귀 메서드에 전달하는 것보다 더 나은 방법이있을 수 있습니다. 그렇다면 누군가 나를 바로 잡습니다.