mirror of
https://git.femboyfinancial.jp/james/lipsync.git
synced 2024-11-30 21:52:00 -08:00
210 lines
9.1 KiB
C#
210 lines
9.1 KiB
C#
/*
|
||
* XmlStaticMemberSerializer.cs
|
||
* Copyright (c) 2009 kbinani
|
||
*
|
||
* This file is part of Boare.Lib.AppUtil.
|
||
*
|
||
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
|
||
* modify it under the terms of the BSD License.
|
||
*
|
||
* Boare.Lib.AppUtil is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
*/
|
||
using System;
|
||
using System.CodeDom.Compiler;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Reflection;
|
||
using System.Xml.Serialization;
|
||
|
||
using Microsoft.CSharp;
|
||
|
||
namespace Boare.Lib.AppUtil {
|
||
|
||
/// <summary>
|
||
/// クラスのstaticメンバーのxmlシリアライズ/デシリアライズを行うclass
|
||
/// </summary>
|
||
public class XmlStaticMemberSerializer {
|
||
/// <summary>
|
||
/// ターゲットとなるクラスから,シリアライズするメンバーを抽出する時に使用
|
||
/// </summary>
|
||
private class MemberEntry {
|
||
/// <summary>
|
||
/// プロパティ/フィールドの名前
|
||
/// </summary>
|
||
public string Name;
|
||
/// <summary>
|
||
/// プロパティ/フィールドの型
|
||
/// </summary>
|
||
public Type Type;
|
||
/// <summary>
|
||
/// プロパティ/フィールドのデフォルト値
|
||
/// </summary>
|
||
public object Default;
|
||
|
||
public MemberEntry( string name, Type type, object default_ ) {
|
||
Name = name;
|
||
Type = type;
|
||
Default = default_;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// シリアライズする対象の型.staticメンバーだけなので,インスタンスではなく型を保持
|
||
/// </summary>
|
||
private Type m_item;
|
||
/// <summary>
|
||
/// シリアライズ/デシリアライズするための内部型
|
||
/// </summary>
|
||
private Type m_config_type = null;
|
||
/// <summary>
|
||
/// m_config_typeで初期化されたシリアライザ
|
||
/// </summary>
|
||
private XmlSerializer m_xs = null;
|
||
|
||
private XmlStaticMemberSerializer() {
|
||
}
|
||
|
||
/// <summary>
|
||
/// 指定された型をシリアライズするための初期化を行います
|
||
/// </summary>
|
||
/// <param name="item"></param>
|
||
public XmlStaticMemberSerializer( Type item ) {
|
||
m_item = item;
|
||
}
|
||
|
||
/// <summary>
|
||
/// シリアライズを行い,ストリームに書き込みます
|
||
/// </summary>
|
||
/// <param name="stream"></param>
|
||
public void Serialize( Stream stream ) {
|
||
if ( m_config_type == null ) {
|
||
GenerateConfigType();
|
||
}
|
||
ConstructorInfo ci = m_config_type.GetConstructor( new Type[]{} );
|
||
object config = ci.Invoke( new object[]{} );
|
||
foreach ( FieldInfo target in m_config_type.GetFields() ) {
|
||
foreach ( PropertyInfo pi in m_item.GetProperties( BindingFlags.Public | BindingFlags.Static ) ) {
|
||
if ( target.Name == pi.Name && target.FieldType.Equals( pi.PropertyType ) && pi.CanRead && pi.CanWrite ) {
|
||
target.SetValue( config, pi.GetValue( m_item, new object[] { } ) );
|
||
break;
|
||
}
|
||
}
|
||
foreach ( FieldInfo fi in m_item.GetFields( BindingFlags.Public | BindingFlags.Static ) ) {
|
||
if ( target.Name == fi.Name && target.FieldType.Equals( fi.FieldType ) ) {
|
||
target.SetValue( config, fi.GetValue( m_item ) );
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
m_xs.Serialize( stream, config );
|
||
}
|
||
|
||
/// <summary>
|
||
/// 指定したストリームを使って,デシリアライズを行います
|
||
/// </summary>
|
||
/// <param name="stream"></param>
|
||
public void Deserialize( Stream stream ) {
|
||
if ( m_config_type == null ) {
|
||
GenerateConfigType();
|
||
}
|
||
object config = m_xs.Deserialize( stream );
|
||
if ( config == null ) {
|
||
throw new ApplicationException( "failed serializing internal config object" );
|
||
}
|
||
foreach ( FieldInfo target in m_config_type.GetFields() ) {
|
||
foreach ( PropertyInfo pi in m_item.GetProperties( BindingFlags.Public | BindingFlags.Static ) ) {
|
||
if ( target.Name == pi.Name && target.FieldType.Equals( pi.PropertyType ) && pi.CanRead && pi.CanWrite ) {
|
||
pi.SetValue( m_item, target.GetValue( config ), new object[] { } );
|
||
break;
|
||
}
|
||
}
|
||
foreach ( FieldInfo fi in m_item.GetFields( BindingFlags.Public | BindingFlags.Static ) ) {
|
||
if ( target.Name == fi.Name && target.FieldType.Equals( fi.FieldType ) ) {
|
||
fi.SetValue( m_item, target.GetValue( config ) );
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// シリアライズ用の内部型をコンパイルし,m_xsが使用できるようにします
|
||
/// </summary>
|
||
private void GenerateConfigType() {
|
||
List<MemberEntry> config_names = CollectScriptConfigEntries( m_item );
|
||
string code = GenerateClassCodeForXmlSerialization( config_names, m_item );
|
||
CSharpCodeProvider provider = new CSharpCodeProvider();
|
||
CompilerParameters parameters = new CompilerParameters();
|
||
parameters.ReferencedAssemblies.Add( "System.Windows.Forms.dll" );
|
||
parameters.ReferencedAssemblies.Add( "System.dll" );
|
||
parameters.ReferencedAssemblies.Add( "System.Drawing.dll" );
|
||
parameters.ReferencedAssemblies.Add( "System.Xml.dll" );
|
||
parameters.GenerateInMemory = true;
|
||
parameters.GenerateExecutable = false;
|
||
parameters.IncludeDebugInformation = true;
|
||
CompilerResults results = provider.CompileAssemblyFromSource( parameters, code );
|
||
Assembly asm = results.CompiledAssembly;
|
||
if ( asm.GetTypes().Length <= 0 ) {
|
||
m_config_type = null;
|
||
m_xs = null;
|
||
throw new ApplicationException( "failed generating internal xml serizlizer" );
|
||
} else {
|
||
m_config_type = (asm.GetTypes())[0];
|
||
m_xs = new XmlSerializer( m_config_type );
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 設定ファイルから読込むための型情報を蒐集
|
||
/// </summary>
|
||
/// <param name="item"></param>
|
||
/// <returns></returns>
|
||
private static List<MemberEntry> CollectScriptConfigEntries( Type item ) {
|
||
List<MemberEntry> config_names = new List<MemberEntry>();
|
||
foreach ( PropertyInfo pi in item.GetProperties( BindingFlags.Static | BindingFlags.Public ) ) {
|
||
object[] attrs = pi.GetCustomAttributes( true );
|
||
foreach ( object obj in attrs ) {
|
||
if ( obj.GetType().Equals( typeof( System.Xml.Serialization.XmlIgnoreAttribute ) ) ) {
|
||
continue;
|
||
}
|
||
}
|
||
if ( pi.CanRead && pi.CanWrite ) {
|
||
config_names.Add( new MemberEntry( pi.Name, pi.PropertyType, pi.GetValue( item, new object[] { } ) ) );
|
||
}
|
||
}
|
||
foreach ( FieldInfo fi in item.GetFields( BindingFlags.Static | BindingFlags.Public ) ) {
|
||
object[] attrs = fi.GetCustomAttributes( true );
|
||
foreach ( object obj in attrs ) {
|
||
if ( obj.GetType().Equals( typeof( System.Xml.Serialization.XmlIgnoreAttribute ) ) ) {
|
||
continue;
|
||
}
|
||
}
|
||
config_names.Add( new MemberEntry( fi.Name, fi.FieldType, fi.GetValue( item ) ) );
|
||
}
|
||
return config_names;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 指定した型から、Reflectionを使ってxmlシリアライズ用のクラスをコンパイルするためのC#コードを作成します
|
||
/// </summary>
|
||
/// <param name="implemented"></param>
|
||
/// <returns></returns>
|
||
private static string GenerateClassCodeForXmlSerialization( List<MemberEntry> config_names, Type item ) {
|
||
// XmlSerialization用の型を作成
|
||
string code = "";
|
||
code += "using System;\n";
|
||
code += "namespace Boare.Lib.AppUtil{\n";
|
||
code += " public class StaticMembersOf" + item.Name + "{\n";
|
||
foreach ( MemberEntry entry in config_names ) {
|
||
code += " public " + entry.Type.ToString() + " " + entry.Name + ";\n";
|
||
}
|
||
code += " }\n";
|
||
code += "}\n";
|
||
return code;
|
||
}
|
||
}
|
||
|
||
}
|