- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在构建一个与第三方交互的库。通信是通过 XML 和 HTTP Posts 进行的。那行得通。
但是,无论使用该库的代码都不需要知道内部类。我的内部对象使用此方法序列化为 XML:
internal static string SerializeXML(Object obj)
{
XmlSerializer serializer = new XmlSerializer(obj.GetType(), "some.domain");
//settings
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
using (StringWriter stream = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, obj);
}
return stream.ToString();
}
}
但是,当我将我的类的访问修饰符更改为 internal
时,我在运行时 遇到异常:
[System.InvalidOperationException] = {"MyNamespace.MyClass is inaccessible due to its protection level. Only public types can be processed."}
该异常发生在上面代码的第一行。
我不希望我的图书馆的类(class)公开,因为我不想公开它们。我可以这样做吗?如何使用我的通用序列化程序使内部类型可序列化?我做错了什么?
最佳答案
来自 Sowmy Srinivasan's Blog - Serializing internal types using XmlSerializer :
Being able to serialize internal types is one of the common requests seen by the XmlSerializer team. It is a reasonable request from people shipping libraries. They do not want to make the XmlSerializer types public just for the sake of the serializer. I recently moved from the team that wrote the XmlSerializer to a team that consumes XmlSerializer. When I came across a similar request I said, "No way. Use DataContractSerializer".
The reason is simple. XmlSerializer works by generating code. The generated code lives in a dynamically generated assembly and needs to access the types being serialized. Since XmlSerializer was developed in a time before the advent of lightweight code generation, the generated code cannot access anything other than public types in another assembly. Hence the types being serialized has to be public.
I hear astute readers whisper "It does not have to be public if 'InternalsVisibleTo' attribute is used".
I say, "Right, but the name of the generated assembly is not known upfront. To which assembly do you make the internals visible to?"
Astute readers : "the assembly name is known if one uses 'sgen.exe'"
Me: "For sgen to generate serializer for your types, they have to be public"
Astute readers : "We could do a two pass compilation. One pass for sgen with types as public and another pass for shipping with types as internals."
They may be right! If I ask the astute readers to write me a sample they would probably write something like this. (Disclaimer: This is not the official solution. YMMV)
using System;
using System.IO;
using System.Xml.Serialization;
using System.Runtime.CompilerServices;
using System.Reflection;
[assembly: InternalsVisibleTo("Program.XmlSerializers")]
namespace InternalTypesInXmlSerializer
{
class Program
{
static void Main(string[] args)
{
Address address = new Address();
address.Street = "One Microsoft Way";
address.City = "Redmond";
address.Zip = 98053;
Order order = new Order();
order.BillTo = address;
order.ShipTo = address;
XmlSerializer xmlSerializer = GetSerializer(typeof(Order));
xmlSerializer.Serialize(Console.Out, order);
}
static XmlSerializer GetSerializer(Type type)
{
#if Pass1
return new XmlSerializer(type);
#else
Assembly serializersDll = Assembly.Load("Program.XmlSerializers");
Type xmlSerializerFactoryType = serializersDll.GetType("Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializerContract");
MethodInfo getSerializerMethod = xmlSerializerFactoryType.GetMethod("GetSerializer", BindingFlags.Public | BindingFlags.Instance);
return (XmlSerializer)getSerializerMethod.Invoke(Activator.CreateInstance(xmlSerializerFactoryType), new object[] { type });
#endif
}
}
#if Pass1
public class Address
#else
internal class Address
#endif
{
public string Street;
public string City;
public int Zip;
}
#if Pass1
public class Order
#else
internal class Order
#endif
{
public Address ShipTo;
public Address BillTo;
}
}
Some astute 'hacking' readers may go as far as giving me the build.cmd to compile it.
csc /d:Pass1 program.cs
sgen program.exe
csc program.cs
关于c# - 如何使用 XmlSerializer 序列化内部类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6156692/
我是一名优秀的程序员,十分优秀!