Чтобы исключить некоторые данные таблицы, но не структуру таблицы. Вот как я это делаю:
Дамп структуры базы данных всех таблиц без каких-либо данных:
mysqldump -u user -p --no-data database > database_structure.sql
Затем удалите базу данных с данными, за исключением исключенных таблиц, и выполните не сбрасывать структуру:
mysqldump -u user -p --no-create-info \
--ignore-table=database.table1 \
--ignore-table=database.table2 database > database_data.sql
Затем, чтобы загрузить его в новую базу данных:
mysql -u user -p newdatabase < database_structure.sql
mysql -u user -p newdatabase < database_data.sql
Это просто неотъемлемое ограничение декларативной сериализации, где информация о типе не встроена в выход.
При попытке конвертировать & lt; Flibble Foo = "10" / & gt;
назад в
public class Flibble {public object Foo {get; задавать; }}
Как сериализатор знает, должен ли он быть int, строка, double (или что-то еще) ...
Чтобы сделать эту работу, вы имеют несколько вариантов, но если вы действительно не знаете до выполнения, самый простой способ сделать это, скорее всего, будет использовать XmlAttributeOverrides .
К сожалению, это будет работать только с базовыми классами, а не интерфейсов. Лучшее, что вы можете сделать, это игнорировать свойство, которого недостаточно для ваших нужд.
Если вы действительно должны оставаться с интерфейсами, у вас есть три реальных варианта:
Ужасная, неприятная плита котла и много повторений, но большинству потребителей этого класса не придется решать проблему:
[XmlIgnore () ] общедоступный объект Foo {get; задавать; } [XmlElement («Foo»)] [EditorVisibile (EditorVisibility.Advanced)] public string FooSerialized {get {/ * здесь код для преобразования любого типа в Foo в строку * /} set {/ * code для анализа сериализованного значения и make Foo экземпляр соответствующего типа * /}}
Это, скорее всего, станет кошмаром для обслуживания ...
Похожие к первому варианту в том, что вы полностью контролируете вещи, но
общедоступный закрытый класс XmlAnything & lt; T & gt; : IXmlSerializable {public XmlAnything () {} общедоступный XmlAnything (T t) {this.Value = t;} public T Value {get; set;} public void WriteXml (XmlWriter writer) {if (Value == null) {writer.WriteAttributeString ("type", "null"); вернуть; } Тип type = this.Value.GetType (); XmlSerializer serializer = новый XmlSerializer (тип); writer.WriteAttributeString ("type", type.AssemblyQualifiedName); serializer.Serialize (writer, this.Value); } public void ReadXml (XmlReader reader) {if (! reader.HasAttributes) выдает новое исключение FormatException («ожидается атрибут типа!»); string type = reader.GetAttribute ("type"); reader.Read (); // употребляем значение if (type == "null") return; // оставляем T по умолчанию по умолчанию XmlSerializer serializer = new XmlSerializer (Type.GetType (type)); this.Value = (T) serializer.Deserialize (reader); reader.ReadEndElement (); } public XmlSchema GetSchema () {return (null); }}
Использование этого будет включать в себя что-то вроде (в проекте P):
public namespace P {public interface IFoo {} public class RealFoo: IFoo { public int X; } public class OtherFoo: IFoo {public double X; } public class Flibble {public XmlAnything & lt; IFoo & gt; Foo; } public static void Main (string [] args) {var x = new Flibble (); x.Foo = новый XmlAnything & lt; IFoo & gt; (новый RealFoo ()); var s = новый XmlSerializer (typeof (Flibble)); var sw = new StringWriter (); s.Serialize (sw, x); ЕЫпе (ЕО); }}
, который дает вам:
& lt;? xml version = "1.0" encoding = "utf-16"? & gt; & lt; MainClass xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: xsd = "http://www.w3.org/2001/XMLSchema" & gt; & lt; Foo type = "P.RealFoo, P, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null" & gt; & Lt; RealFoo & GT; & Lt; & Х при 0 & л; / Х & GT; & Lt; / RealFoo & GT; & Lt; / Foo & GT; & Lt; / MainClass & GT;
Это, очевидно, более громоздко для пользователей этого класса, хотя и позволяет избежать большого количества плиты котла.
. Счастливый носитель может объединить идею XmlAnything в свойство «поддержки» первый метод. Таким образом, большая часть ворчания выполняется для вас, но потребители этого класса не подвергаются влиянию, кроме путаницы с интроспекцией.
К несчастью для меня, у меня был случай, когда класс, который должен быть сериализован, имел свойства с интерфейсами как свойствами, поэтому мне нужно было рекурсивно обрабатывать каждое свойство. Кроме того, некоторые свойства интерфейса были отмечены как [XmlIgnore], поэтому я хотел пропустить их. Я взял идеи, которые я нашел в этой теме, и добавил некоторые вещи к ней, чтобы сделать ее рекурсивной. Здесь показан только код десериализации:
void main () {var serializer = GetDataContractSerializer & lt; MyObjectWithCascadingInterfaces & gt; (); используя (FileStream stream = новый FileStream (xmlPath, FileMode.Open)) {XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader (поток, новый XmlDictionaryReaderQuotas ()); var obj = (MyObjectWithCascadingInterfaces) serializer.ReadObject (reader); // ваш код здесь}} DataContractSerializer GetDataContractSerializer & lt; T & gt; (), где T: new () {Тип [] types = GetTypesForInterfaces & lt; T & gt; (); // Отфильтровать дубликаты Тип [] result = types.ToList (). Distinct (). ToList (). ToArray (); var obj = new T (); вернуть новый DataContractSerializer (obj.GetType (), типы); } Тип [] GetTypesForInterfaces & lt; T & gt; (), где T: new () {return GetTypesForInterfaces (typeof (T)); } Тип [] GetTypesForInterfaces (Тип T) {Тип [] result = new Тип [0]; var obj = Activator.CreateInstance (T); // получить тип для всех свойств интерфейса, которые не помечены как «XmlIgnore» Type [] types = T.GetProperties () .Where (p = & gt; p.PropertyType.IsInterface & amp;! p.GetCustomAttributes (typeof ( System.Xml.Serialization.XmlIgnoreAttribute), false) .Any ()). Выбрать (p = & gt; p.GetValue (obj, null) .GetType ()) .ToArray (); result = result.ToList (). Concat (types.ToList ()). ToArray (); // делаем то же самое для каждого из типов, определенных foreach (тип t в типах) {Type [] embeddedTypes = GetTypesForInterfaces (t); result = result.ToList (). Concat (embeddedTypes.ToList ()). ToArray (); } return result; }
Я нашел более простое решение (вам не нужен DataContractSerializer), благодаря этому блогу здесь: XML-сериализация производных типов, когда базовый тип находится в другом пространстве имен или в DLL
< blockquote>Но в этой реализации могут подняться две проблемы:
(1) Что делать, если DerivedBase не находится в пространстве имен класса Base или еще хуже в проекте, который зависит от пространства имен Base, поэтому Base не может XMLInclude DerivedBase
(2) Что делать, если у нас есть только класс Base как dll, поэтому Base не может XMLInclude DerivedBase
До сих пор ...
Таким образом, решение двух проблем заключается в использовании XmlSerializer Constructor (Type, array []):
XmlSerializer ser = new XmlSerializer (typeof (A), новый тип [] { TypeOf (DerivedBase)});
Подробный пример представлен здесь в MSDN: XmlSerializer Constructor (Тип, extraTypesArray [])
Мне кажется, что для DataContracts или XML-файлы Soap, вам нужно проверить XmlRoot, как указано здесь в этом вопросе SO .
Аналогичный ответ здесь на SO , но он не является " t отмечен как один, поскольку он, по-видимому, уже не рассматривал ОП.
Замена интерфейса IModelObject абстрактным или конкретным типом и использование наследования с XMLInclude возможно, но похоже на уродливое обходное решение.
blockquote>Если можно использовать абстрактный Я бы рекомендовал этот маршрут. Он по-прежнему будет чище, чем использование ручного сериализации. Единственная проблема, которую я вижу с абстрактной базой, заключается в том, что вам все еще нужен конкретный тип? По крайней мере, так я использовал его в прошлом, что-то вроде:
public abstract class IHaveSomething {public abstract string Something {get; задавать; }} public class MySomething: IHaveSomething {string _sometext; public override string Что-то {get {return _sometext; } set {_sometext = значение; }}} [XmlRoot ("abc")] public class seriaized {[XmlElement ("item", typeof (MySomething))] общедоступные данные IHaveSomething; }
Решением этого является использование отражения с помощью DataContractSerializer. Вам даже не нужно отмечать свой класс [DataContract] или [DataMember]. Он будет сериализовать любой объект, независимо от того, имеет ли он свойства типа интерфейса (включая словари) в xml. Вот простой метод расширения, который будет сериализовать любой объект в XML, даже если он имеет интерфейсы (обратите внимание, что вы можете настроить его так же, как и рекурсивно).
public static XElement ToXML (этот объект o) {Введите t = o.GetType (); Тип [] extraTypes = t.GetProperties () .Where (p = & gt; p.PropertyType.IsInterface) .Выберите (p = & gt; p.GetValue (o, null) .GetType ()) .ToArray (); DataContractSerializer serializer = новый DataContractSerializer (t, extraTypes); StringWriter sw = new StringWriter (); XmlTextWriter xw = новый XmlTextWriter (sw); serializer.WriteObject (xw, o); return XElement.Parse (sw.ToString ()); }
, что делает выражение LINQ, перечисляет каждое свойство, возвращает каждое свойство, являющееся интерфейсом, получает значение этого свойства (базового объекта), получает тип этого конкретного объекта помещает его в массив и добавляет это в список известных типов сериализатора.
Теперь сериализатор знает, как о типах, которые он сериализует, чтобы он мог выполнять свою работу.
в моем проекте, у меня есть List & lt; IFormatStyle & gt; FormatStyleTemplates; содержащие различные типы.
Затем я использую решение «XmlAnything» сверху, чтобы сериализовать этот список разных типов.
[Browsable (false)] [EditorBrowsable (EditorBrowsableState.Never)] [XmlArray («FormatStyleTemplates»)] [XmlArrayItem («FormatStyle»)] общедоступный XmlAnything & lt; IFormatStyle & gt; ; [] FormatStyleTemplatesXML {get {return FormatStyleTemplates.Select (t = & gt; новый XmlAnything & lt; IFormatStyle & gt; (t)). ToArray (); } set {// читаем значения обратно в какой-то новый объект или что-то вроде m_FormatStyleTemplates = new FormatStyleProvider (null, true); value.ForEach (t = & gt; m_FormatStyleTemplates.Add (t.Value)); }}
Если вы знаете, что у вас есть разработчики интерфейса, достаточно простой хак, который вы можете использовать, чтобы получить тип интерфейса для сериализации без написания кода разбора:
public interface IInterface {} public class KnownImplementor01: IInterface {} public class KnownImplementor02: IInterface {} public class KnownImplementor03: IInterface {} public class ToSerialize {[XmlIgnore] public IInterface InterfaceProperty {get; задавать; } [XmlArray («интерфейс»)] [XmlArrayItem («ofTypeKnownImplementor01», typeof (KnownImplementor01)] [XmlArrayItem («ofTypeKnownImplementor02», typeof (KnownImplementor02)] [XmlArrayItem («ofTypeKnownImplementor03», typeof (KnownImplementor03)] public object [] InterfacePropertySerialization {get {return new [] {InterfaceProperty}} set {InterfaceProperty = (IInterface) value.Single ();}}}
Получившийся xml должен выглядеть примерно так:
& lt; interface & gt; & lt; ofTypeKnownImplementor01 & gt; & lt;! - etc ... - & gt;
К сожалению, нет простого ответа, поскольку сериализатор не знает, что сериализовать для интерфейса. Я нашел более полное объяснение того, как обходиться это на MSDN
Вы можете использовать ExtendedXmlSerializer . Этот сериализатор поддерживает сериализацию свойства интерфейса без каких-либо трюков.
var serializer = new ConfigurationContainer (). UseOptimizedNamespaces (). Create (); var obj = new Пример {Model = new Model {Name = "name"}}; var xml = serializer.Serialize (obj);
Ваш xml будет выглядеть так:
& lt;? xml version = "1.0" encoding = "utf-8"? & gt; & lt; Пример xmlns: exs = "https://extendedxmlserializer.github.io/v2" xmlns = "clr-namespace: ExtendedXmlSerializer.Samples.Simple; assembly = ExtendedXmlSerializer.Samples" & gt; & lt; Модель exs: type = "Model" & gt; & Lt; & Имя GT; имя & л; / Имя & GT; & Lt; / Модель & GT; & Lt; / Пример & GT;
ExtendedXmlSerializer поддерживает .net 4.5 и .net Core.