Incercand sa convertesc un cod Java la cod .NET, m-am lovit de problema implementarii unui modul care sa faca ceea ce face digester-ul java. Am inceput sa caut pe internet si dupa ceva timp am gasit o librarie care aparent putea face ceea ce aveam eu nevoie.

NDigester este implementarea .NET a pachetului Jakarta Commons-Digester. Pe baza unor fisiere XML de configurare, NDigester ofera posibilitatea initializarii de obiecte in cadrul aplicatiei pe baza configurarilor XML.

NDigester se poate descarca de la adresa: http://sourceforge.net/projects/ndigester/

L-am descarcat si am incercat sa-l folosesc. M-am lovit de cateva incompatibilitati. Cum am rezolvat incompatibilitatile? Am refacut fisierele XML care functionau in Java, conform cerintelor NDigester astfel:

1. In cadrul regulei object-create-rule am schimbat classname cu typeName

Exemplu:
<object-create-rule classname="ro.atypIQ.LL.xml.MyObjectXML" />
se transforma in
<
object-create-rule typeName="ro.atypIQ.LL.xml.MyObjectXML, MyAssembly" />

Nota: typeName va contine numele assembly-ului unde se gasesc resursele.

2. Am schimbat regula call-method-rule cu property-setter-rule, iar in cadrul regulei am schimbat methodname cu propertyName, iar paramcount dispare

Exemplu:
<
call-method-rule pattern="name" methodname="setName" paramcount="0" />
se transforma in
<
property-setter-rule pattern="name" propertyName="Name"/>

3. Am schimbat regula alias cu set-property-rule, iar in cadrul regulei am schimbat attr-name cu value si prop-name cu name.

Exemplu:
<
alias attr-name="name" prop-name="name" />
se transforma in
<
set-property-rule name="Name" value="name" />

4. Am schimbat regula bean-property-setter-rule cu property-setter-rule.

Exemplu:
<
bean-property-setter-rule pattern="name" propertyName="name" />
se transforma in
<
property-setter-rule pattern="name" propertyName="Name" />

Atentie: Vor trebui redenumite si numele de functii si de proprietati acolo unde este cazul.


Pana acum totul a decurs ok, cu o singura exceptie. Se pare ca NDigester are un bug. Rezolvarea mea presupune modificarea functiei OnBegin() din clasa SetPropertyRule.cs.

Functia originala:

public override void OnBegin()
{
    // determine actual 'name' and 'value'
    string actualName = null;
    string actualValue = null;

    for(int i=0; istring name = digester.Attributes.GetKey(i);
        string value = digester.Attributes[i];
        if(name == this.name)
        {
            actualName = value;
        }
        else if(name == this.value)
        {
            actualValue = value;
        }
    }

    // populate object's property
    object top = digester.Peek();
    PropertyInfo prop = top.GetType().GetProperty(actualName, BindingFlags.Public | BindingFlags.Instance);
    prop.SetValue(top, Convert.ChangeType(actualValue, prop.PropertyType), null);
}

Functia modificata:

public override void OnBegin()
{
    //determine actual 'name' and 'value'
        string actualName = null;
        string actualValue = null;

        for(int i=0; istring name = digester.Attributes.GetKey(i);
            string value = digester.Attributes[i];
            if(name == this.value)
                {
                    actualName = this.name;
                    actualValue = value;
                }
        }

        if (actualName == null || actualName.Equals(""))
                return;

        // populate object's property
        object top = digester.Peek();
        PropertyInfo prop = top.GetType().GetProperty(actualName, BindingFlags.Public | BindingFlags.Instance);
        prop.SetValue(top, Convert.ChangeType(actualValue, prop.PropertyType), null);
}

Acum, totul functioneaza perfect!