Как я могу создать класс из XSD, но сохранить атрибуты одинаковыми?

1

Я получаю XML из базы данных и пытаюсь обработать его в моей системе. Я создал класс из XSD, который я получил от другой команды. Проблема, с которой я столкнулась, заключается в том, что прямо сейчас имена свойств в XSD не совпадают с именами свойств в моем приложении (типичные). Для меня, чтобы построить объект, который я могу использовать, я должен создать объект и объединить его вместе с XML. Как это:

DynamicEntity auth = new DynamicEntity(EntityAuthorization);
auth.Properties["DealerId] = authprm.new_dealerid[0].Value;
auth.Properties["CarId"] = authprm.new_carid[0].Value;
etc...

Я могу потенциально установить от 40 до 100 свойств. Я думал о применении XmlElement к атрибутам класса, но каждый раз, когда мне приходится регенерировать класс (из XML), я потеряю XmlElements, который я применил ранее. Какие предложения?

Всем спасибо!

Теги:
serialization
xsd

1 ответ

1

Вы можете использовать метаданные "класс друзей", поместив в свой класс метаданныеTypeAttribute. Я бы сделал класс, который генерируется частично, если он еще не создан, а затем создает еще один частичный класс и добавляет атрибут MetadataType к этому классу. Затем, если вы регенерируете класс из XSD, и он не является частичным, компилятор будет жаловаться, и вы запомните его частичным.

Мне не нравятся "классы приятелей", потому что свойства дублируются, а не DRY, но это может быть решение, которое вы ищете. Для простого обзора класса метаданных, который обычно относится к атрибутам проверки, но он работает для любых атрибутов, вы можете найти на MS здесь

Вы можете найти ответ на qaru.site/questions/7963941/... о том, как узнать XmlSerializer о классе друзей.

Обновить

Теперь, когда я думаю об этом, если вы не хотите использовать класс Buddy, вы можете быстро создать api для настройки XML-сериализатора.

Мы сохраним класс CustomAttributeProvider из XMLSerializer с вопросом класса собеседника, но вместо этого создадим класс XmlSerializerConfigurator.

public class XmlSerializerConfigurator<T>
{
    private readonly XmlAttributeOverrides _xmlAttributeOverrides;

    public XmlSerializerConfigurator(XmlAttributeOverrides xmlAttributeOverrides)
    {
        _xmlAttributeOverrides = xmlAttributeOverrides;
    }

    public XmlSerializerConfigurator() : this(new XmlAttributeOverrides())
    {
    }

    /// <summary>
    /// Adds attributes to properties or fields and strongly typed
    /// </summary>
    /// <typeparam name="TData"></typeparam>
    /// <param name="property"></param>
    /// <param name="xmlAttributes"></param>
    /// <returns></returns>
    public XmlSerializerConfigurator<T> AddPropertyOrFieldAttributes<TData>(Expression<Func<T, TData>> property,
                                                    params Attribute[] xmlAttributes)
    {
        var memberName = property.GetName();
        _xmlAttributeOverrides.Add(typeof (T), memberName,
                                   new XmlAttributes(new CustomAttributeProvider(xmlAttributes)));
        return this;
    }

    /// <summary>
    /// Adds class level attributes
    /// </summary>
    /// <param name="xmlAttributes"></param>
    /// <returns></returns>
    public XmlSerializerConfigurator<T> AddClassLevelAttributes(params Attribute[] xmlAttributes)
    {
        _xmlAttributeOverrides.Add(typeof(T), new XmlAttributes(new CustomAttributeProvider(xmlAttributes)));
        return this;
    }

    /// <summary>
    /// Creates an XmlSerializerConfigurator that is tied to the main one
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <returns></returns>
    public XmlSerializerConfigurator<K> ChildClassConfigurator<K>()
    {
        // passes in own XmlAttributeOverrides and since object reference it will fill the same object 
        return new XmlSerializerConfigurator<K>(_xmlAttributeOverrides);
    }

    /// <summary>
    /// Returns back an XmlSerializer with this configuration
    /// </summary>
    /// <returns></returns>
    public XmlSerializer GetSerializer()
    {
        return new XmlSerializer(typeof(T), _xmlAttributeOverrides);
    }
}

Этот класс позволит вам настроить, какие атрибуты относятся к классу/свойству Сериализатора, и не полагаться на класс приятеля. Нам нужны атрибуты ChildClassAttributes, если класс имеет другой класс, как свойство, чтобы разрешить настройку этого класса.

Также я использую метод расширения, возвращающий свойство или поле из выражения GetName.

public static string GetName<TEntity, TData>(this Expression<Func<TEntity, TData>> field)
{
    var name = "";

    if (field.Body is MemberExpression)
    {
        var body = field.Body as MemberExpression;
        var ebody = body.Expression as MemberExpression;

        if (ebody != null)
        {
            name = ebody.Member.Name + ".";
        }
        name = name + body.Member.Name;
    }
    else if (field.Body is UnaryExpression)
    {
        var ubody = field.Body as UnaryExpression;
        var body = ubody.Operand as MemberExpression;
        var ebody = body.Expression as MemberExpression;

        if (ebody != null)
        {
            name = ebody.Member.Name + ".";
        }
        name = name + body.Member.Name;
    }
    else if (field.Body is ConstantExpression)
    {
        var cbody = field.Body as ConstantExpression;
        name = cbody.Value.ToString();
    }
    else
    {
        throw new InvalidOperationException(String.Format("{0} not supported.", field));
    }

    return name;
}

Теперь вы можете использовать/настроить его таким образом

var xmlConfiguration = new XmlSerializerConfigurator<Group>();
xmlConfiguration.AddPropertyOrFieldAttributes(x => x.Employees, new XmlArrayItemAttribute(typeof (Employee)),
                                              new XmlArrayItemAttribute(typeof (Manager)));
xmlConfiguration.AddClassLevelAttributes(new XmlRootAttribute("GroupName"));
var childConfiguration = xmlConfiguration.ChildClassConfigurator<Employee>();
childConfiguration.AddPropertyOrFieldAttributes(x => x.FullName, new XmlElementAttribute("Name"));
var xmlSerializer = xmlConfiguration.GetSerializer();

Теперь все свойства и поля строго типизированы и не дублируются в классе друзей.

  • 0
    Спасибо Человек, я ценю это!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню