martes, 15 de junio de 2010

Updating SPListItem

En un proyecto en el que estoy trabajando me he encontrado con la necesidad de añadir datos a listas en tiempo de despliegue, a partir de un archivo xml, más o menos como lo que haria la feature listinstance cuando le especificamos un child element data.

Más info...

Una vez leído este fichero xml obtenemos un diccionario key-value, con los fields (keys) de nuestro item y sus valores (value), en nuestro caso ambos serian string.

El problema con el que nos encontramos es que en un SPListItem almacenamos objects, y por lo tanto tendriamos que parsear de alguna forma nuestros strings al tipo de campo que requiere ese field. Para saberlo necesitamos consultar el SPField y este SPField tiene un SPFieldValueType que nos permite determinar el tipo de dato que se almacena en ese campo. Luego añadimos un poco de reflection y utilizamos una función muy interesante que he descubierto, Convert.ChangeType, que permite cambiar de un tipo a otro, y eureka!!! Tenemos un extensión method super útil.

/// 
/// Update an item using a dictionary with key-value pairs
///

/// The item
/// The data collection
public static void Update(this SPListItem item, Dictionary data)
{
bool overwriteVersion = false;

foreach (String internalFieldName in data.Keys)
{
if (item.Fields.Contains(internalFieldName))
{
SPField field = item.Fields.GetFieldByInternalName(internalFieldName);

ConstructorInfo constructor = field.FieldValueType.GetConstructor(new Type[] { typeof(string) });

if (constructor != null)
{
item[internalFieldName] = constructor.Invoke(new object[] { data[internalFieldName]});
}
else
{
item[internalFieldName] = Convert.ChangeType(data[internalFieldName], field.FieldValueType, CultureInfo.InvariantCulture);
}

if (field.ReadOnlyField || field.Type == SPFieldType.Computed) overwriteVersion = true;
}
}

if (overwriteVersion) item.UpdateOverwriteVersion();
else item.Update();
}

No hay comentarios: