ファイルに保存したいさまざまな種類のオブジェクトがc#にありますが(XMLが推奨されます)、クラスは自分で作成したものではなく、DLLからのものであるため、シリアル化を使用できません。
これに対する最善の解決策は何ですか?
ファイルに保存したいさまざまな種類のオブジェクトがc#にありますが(XMLが推奨されます)、クラスは自分で作成したものではなく、DLLからのものであるため、シリアル化を使用できません。
これに対する最善の解決策は何ですか?
私は最終的にJavaScriptSerializerを使用しましたが、それはまさに私が探していたものを実行します。
List<Person> persons = new List<Person>();
persons.Add(new Person(){Name = "aaa"});
persons.Add(new Person() { Name = "bbb" });
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
var strData = javaScriptSerializer.Serialize(persons);
var persons2 = javaScriptSerializer.Deserialize<List<Person>>(strData);
シリアル化できないオブジェクトを指定して、XMLに「シリアル化」する簡単な拡張メソッドを作成しました。それはかなりラフで、多くのチェックを行わず、生成されるXMLは、ニーズに合わせて簡単に調整できます。
public static string SerializeObject<T>(this T source, bool serializeNonPublic = false)
{
if (source == null)
{
return null;
}
var bindingFlags = BindingFlags.Instance | BindingFlags.Public;
if (serializeNonPublic)
{
bindingFlags |= BindingFlags.NonPublic;
}
var properties = typeof(T).GetProperties(bindingFlags).Where(property => property.CanRead).ToList();
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb))
{
writer.WriteStartElement(typeof(T).Name);
if (properties.Any())
{
foreach (var property in properties)
{
var value = property.GetValue(source, null);
writer.WriteStartElement(property.Name);
writer.WriteAttributeString("Type", property.PropertyType.Name);
writer.WriteAttributeString("Value", value.ToString());
writer.WriteEndElement();
}
}
else if (typeof(T).IsValueType)
{
writer.WriteValue(source.ToString());
}
writer.WriteEndElement();
}
return sb.ToString();
}
私はこのクラスでそれをテストしました:
private sealed class Test
{
private readonly string name;
private readonly int age;
public Test(string name, int age)
{
this.name = name;
this.age = age;
}
public string Name
{
get
{
return this.name;
}
}
public int Age
{
get
{
return this.age;
}
}
}
だけでなく、数3
とobject
。結果のXMLは次のようになります。
<?xml version="1.0" encoding="utf-16"?>
<Test>
<Name Type="String" Value="John Doe" />
<Age Type="Int32" Value="35" />
</Test>
<?xml version="1.0" encoding="utf-16"?>
<Int32>3</Int32>
<?xml version="1.0" encoding="utf-16"?>
<Object />
それぞれ。
DLLのシリアライズ不可能なクラスの周りに独自のシリアライズ可能なラッパーを記述します。
編集:AutoMapperはコメントで提案されており、まだ聞いたことがありませんでしたが、ラッパーを自分で作成する代わりに、間違いなくそれを使用するようになりました。シリアル化できないオブジェクトの内部状態の一部をキャプチャするために必要なリフレクションがない限り(可能な場合)、AutoMapperがそこに提供するものがあるかどうか、またはラッパーでキャプチャできるかどうかを確認する必要があります。 。
返されたDLLのオブジェクトを模倣するPOCO(Plain Old Class Object)クラスを作成します。一般に、.NET 3.5以降を使用している場合は、LINQを使用できます。私は、Linqがオブジェクトを他のクラスに配置したり、それらに対して並べ替えやその他の操作を実行したりすることを好みます。
たとえば、returnオブジェクトをダミーにする簡単な例を次に示します。もちろん、DLLには多くの異なるオブジェクトがあり、これを複数回実行する可能性があることに注意してください。また、メインで行うのではなく、再利用性のためにメソッドを独自のクラスにまとめます。しかし、ここに概念の簡単な証明があります
using System;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Xml.Linq;
namespace ExampleSerializer
{
class Program
{
// example class to serialize
[Serializable]
public class SQLBit
{
[XmlElement("Name")]
public string Name { get; set; }
[XmlText]
public string data { get; set; }
}
// example class to populate to get test data
public class example
{
public string Name { get; set; }
public string data { get; set; }
}
static void Main(string[] args)
{
string s = "";
// make a generic and put some data in it from the test
var ls = new List<example> { new example { Name = "thing", data = "data" }, new example { Name = "thing2", data = "data2" } };
// make a second generic and put data from the first one in using a lambda
// statement creation method. If your object returned from DLL is a of a
// type that implements IEnumerable it should be able to be used.
var otherlist = ls.Select(n => new SQLBit
{
Name = n.Name,
data = n.data
});
// start a new xml serialization with a type.
XmlSerializer xmler = new XmlSerializer(typeof(List<SQLBit>));
// I use a textwriter to start a new instance of a stream writer
TextWriter twrtr = new StreamWriter(@"C:\Test\Filename.xml");
// Serialize the stream to the location with the list
xmler.Serialize(twrtr, otherlist);
// Close
twrtr.Close();
// TODO: You may want to put this in a try catch wrapper and make up your
// own classes. This is a simple example.
}
}
}
質問ヘッダーの「シリアル化なし」という用語は誤解を招くと思います。
私があなたを正しく理解していれば、serilisation-attributesを持たないオブジェクトをシリアル化したいと思うでしょう。
あなたのために仕事をすることができるsharpserializerやprotobuf-netのようなライブラリがあります。