Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Dudas c#

Iniciado por AbelNightroad, 29 de Junio de 2006, 11:03:22 PM

« anterior - próximo »

AbelNightroad

Algunas dudas de principiante....

- Como puedo imprimir comillas dobles con Console.WriteLine ?

- Se pueden añadir elementos a un array sobre la marcha (array dinamico)? O para eso no hay otra que usar clases como StringCollection?

- Tengo un objeto que crea 100000 instancias de otro tipo de objetos que a su vez crean unos 10~20 objetos (algunos de ellos son StringCollection o ArrayList, aunque con muy pocos elementos 1~10). ¿Es normal que el programa me chupe 300Mb de RAM ? :roll: ¿alguna alternativa? Basicamente me interesa tener un arbol de strings y poder añadir strings en cualquier rama del arbol (es realidad es archivo XML de 40MB que he cargado a "mano" [con XmlTextReader]) ¿cual seria la forma eficiente en terminos de memoria de hacerlo?

zankius
bel Nightroad (a.k.a. Lord Trancos)

Vicente

Hola,

1) puedes escaparlas con \"
2) los arrays no son dinámicos de tamaño. Para eso usa las clases de System.Collections.ArrayList o System.Collections.Generic.List<T>
3) si lo único que te interesa son los strings y su posición en el arbol, quizás podrías usar tu un arbol casero, ya que los objetos de tipo XmlElement, XmlNode y demás son bastante pesaditos. De todas formas 300 MB me parece demasiado la verdad. Se puede ver que estás haciendo?

Un saludo!

Vicente

AbelNightroad

Cita de: "Vicente"
1) puedes escaparlas con \"

Gracias

Cita de: "Vicente"
2) los arrays no son dinámicos de tamaño. Para eso usa las clases de System.Collections.ArrayList o System.Collections.Generic.List<T>

Cachis...

Cita de: "Vicente"
3) si lo único que te interesa son los strings y su posición en el arbol, quizás podrías usar tu un arbol casero, ya que los objetos de tipo XmlElement, XmlNode y demás son bastante pesaditos. De todas formas 300 MB me parece demasiado la verdad. Se puede ver que estás haciendo?

Efectivamente estoy intentando usar un arbol casero. Me chupa 300Mb. Si en lugar de mi "arbol" simplemente cargo el XML con un XmlDocument (sin hacer nada mas), chupa 200Mb. De hecho hice lo del arbol casero pq me acelerará las busquedas y pq tenia la esperanza de consumir menos memoria que el XmlDocument.

Sip, claro, se puede ver que estoy haciendo (aunque no tiene nada q ver con vieojuegos :P)

JMDictEntry.cs

using System;
using System.Collections;
using System.Collections.Specialized;

namespace Pulsar.Nihongo
{
[Serializable]
public class k_ele_data
{
public string keb;
public StringCollection ke_inf = new StringCollection();
public StringCollection ke_pri = new StringCollection();

public void Set_keb(string p_value)
{
keb = p_value;
}

public void Add_ke_inf(string p_value)
{
ke_inf.Add(p_value);
}

public void Add_ke_pri(string p_value)
{
ke_pri.Add(p_value);
}

public k_ele_data()
{
}
}

[Serializable]
public class r_ele_data
{
public string reb;
public bool re_nokanji;
public StringCollection re_restr = new StringCollection();
public StringCollection re_inf = new StringCollection();
public StringCollection re_pri = new StringCollection();

public void Set_reb(string p_value)
{
reb = p_value;
}

public void Set_re_nokanji(bool p_value)
{
re_nokanji = p_value;
}

public void Add_re_restr(string p_value)
{
re_restr.Add(p_value);
}

public void Add_re_inf(string p_value)
{
re_inf.Add(p_value);
}

public void Add_re_pri(string p_value)
{
re_pri.Add(p_value);
}

public r_ele_data()
{
re_nokanji = false;
}
}

[Serializable]
public class info_data
{
public StringCollection lang = new StringCollection();
public StringCollection dial = new StringCollection();

public void Add_lang(string p_value)
{
lang.Add(p_value);
}

public void Add_dial(string p_value)
{
dial.Add(p_value);
}

public info_data()
{
}
}

[Serializable]
public class gloss_data
{
public string translation;
public string g_lang;

public gloss_data(string p_value, string p_lang)
{
translation = p_value;
g_lang = p_lang;
}
}

[Serializable]
public class sense_data
{
public StringCollection stagk = new StringCollection();
public StringCollection stagr = new StringCollection();
public StringCollection pos   = new StringCollection();
public StringCollection xref  = new StringCollection();
public StringCollection ant   = new StringCollection();
public StringCollection field = new StringCollection();
public StringCollection misc  = new StringCollection();
public StringCollection s_inf = new StringCollection();
public ArrayList gloss = new ArrayList();

public void Add_stagk(string p_value)
{
stagk.Add(p_value);
}

public void Add_stagr(string p_value)
{
stagr.Add(p_value);
}

public void Add_pos(string p_value)
{
pos.Add(p_value);
}

public void Add_xref(string p_value)
{
xref.Add(p_value);
}

public void Add_ant(string p_value)
{
ant.Add(p_value);
}

public void Add_field(string p_value)
{
field.Add(p_value);
}

public void Add_misc(string p_value)
{
misc.Add(p_value);
}

public void Add_s_inf(string p_value)
{
s_inf.Add(p_value);
}

public void Add_gloss(string p_value, string p_lang)
{
gloss.Add(new gloss_data(p_value, p_lang));
}

public sense_data()
{
}
}

/// <summary>
/// This class manages a JMDict Entry.
/// </summary>
[Serializable]
public class JMDictEntry
{
#region serialized properties
/// <summary> Entry sequence number (ent_seq).
public string ent_seq;
public ArrayList k_ele = new ArrayList();
public ArrayList r_ele = new ArrayList();
public ArrayList info  = new ArrayList();
public ArrayList sense = new ArrayList();
#endregion

#region k_ele
public k_ele_data Last_k_ele
{
get
{
if (k_ele.Count > 0)
 { return (k_ele_data)k_ele[k_ele.Count-1]; }
   else { return null; }
}
}

public void Add_k_ele(k_ele_data p_ref)
{
k_ele.Add(p_ref);
}
#endregion

#region r_ele
public r_ele_data Last_r_ele
{
get
{
if (r_ele.Count > 0)
 { return (r_ele_data)r_ele[r_ele.Count-1]; }
   else { return null; }
}
}

public void Add_r_ele(r_ele_data p_ref)
{
r_ele.Add(p_ref);
}
#endregion

#region info
public info_data Last_info
{
get
{
if (info.Count > 0)
 { return (info_data)info[info.Count-1]; }
   else { return null; }
}
}

public void Add_info(info_data p_ref)
{
info.Add(p_ref);
}
#endregion

#region sense
public sense_data Last_sense
{
get
{
if (sense.Count > 0)
{ return (sense_data)sense[sense.Count-1]; }
 else { return null; }
}
}

public void Add_sense(sense_data p_ref)
{
sense.Add(p_ref);
}
#endregion

public JMDictEntry()
{

}
}
}


JMDict.cs

using System;
using System.IO;
using System.Xml;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Pulsar.Nihongo
{
/// <summary>
/// Class for loading and walking through JMDict.
/// </summary>
[Serializable]
public class JMDict
{
#region serialized properties
public JMDictEntry[] Entries;
#endregion

#region non-serialized properties
/// <summary> Will throw exceptions when set to true.
[NonSerialized]public bool ThrowExceptions;
#endregion

#region private methods
/// <summary>
/// Used internally by the class to return error strings or throwing exceptions.
/// </summary>
/// <param name="ex">Original exception.</param>
/// <returns>Error string.</returns>
private string errString(Exception p_ex)
{
if (ThrowExceptions)
{
throw(p_ex);
}
else
{
return("ERROR [" + this.ToString() + "]: " + p_ex.ToString());
}
}
#endregion

#region public methods
/// <summary>
/// This function will load JMDict from original JMDict XML file, into memory.
/// </summary>
/// <param name="_filename">JMDict path and filename.</param>
/// <returns>Error description, or an empty string if no error.</returns>
public string LoadFromFile(string p_filename)
{
XmlTextReader _reader;
string _tmp = "";

// open JMDict
try
{
_reader = new XmlTextReader(p_filename);
}
catch (Exception ex)
{
// return error description
return errString(ex);
}

// load it into memory
try
{
// 1st pass - read XML and just count how many entries are there
int _entryCnt = 0;
while (_reader.Read())
{
if ((_reader.NodeType == XmlNodeType.Element) && (_reader.Name == "entry")) { _entryCnt++; }
}

// initialize array for entries
Entries = new JMDictEntry[_entryCnt];

// read again (must be a better way of doing this)
_reader.Close();
_reader = new XmlTextReader(p_filename);

// 2nd pass - read Data
_entryCnt = -1;
while (_reader.Read())
{
switch (_reader.NodeType)
{
// element
case XmlNodeType.Element:
switch (_reader.Name)
{
// ENTRY ---------------------------------------------------
// new entry!
case "entry":
_entryCnt++;
Entries[_entryCnt] = new JMDictEntry();
break;

case "ent_seq":
_reader.Read();
Entries[_entryCnt].ent_seq = _reader.Value;
break;

// K_ELE ---------------------------------------------------
// new kanji
case "k_ele":
Entries[_entryCnt].Add_k_ele(new k_ele_data());
break;

case "keb":
_reader.Read();
Entries[_entryCnt].Last_k_ele.Set_keb(_reader.Value);
break;

case "ke_inf":
_reader.Read();
Entries[_entryCnt].Last_k_ele.Add_ke_inf(_reader.Name);
break;

case "ke_pri":
_reader.Read();
Entries[_entryCnt].Last_k_ele.Add_ke_pri(_reader.Value);
break;

// R_ELE ---------------------------------------------------
// new reading
case "r_ele":
Entries[_entryCnt].Add_r_ele(new r_ele_data());
break;

case "reb":
_reader.Read();
Entries[_entryCnt].Last_r_ele.Set_reb(_reader.Value);
break;

case "re_nokanji":
Entries[_entryCnt].Last_r_ele.Set_re_nokanji(true);
break;

case "re_restr":
_reader.Read();
Entries[_entryCnt].Last_r_ele.Add_re_restr(_reader.Value);
break;

case "re_inf":
_reader.Read();
Entries[_entryCnt].Last_r_ele.Add_re_inf(_reader.Name);
break;

case "re_pri":
_reader.Read();
Entries[_entryCnt].Last_r_ele.Add_re_pri(_reader.Value);
break;

// SENSE ---------------------------------------------------
// new info
case "info":
Entries[_entryCnt].Add_info(new info_data());
break;

case "lang":
_reader.Read();
Entries[_entryCnt].Last_info.Add_lang(_reader.Value);
break;

case "dial":
_reader.Read();
Entries[_entryCnt].Last_info.Add_dial(_reader.Value);
break;

// SENSE ---------------------------------------------------
// new sense
case "sense":
Entries[_entryCnt].Add_sense(new sense_data());
break;

case "stagk":
_reader.Read();
Entries[_entryCnt].Last_sense.Add_stagk(_reader.Value);
break;

case "stagr":
_reader.Read();
Entries[_entryCnt].Last_sense.Add_stagr(_reader.Value);
break;

case "pos":
_reader.Read();
Entries[_entryCnt].Last_sense.Add_pos(_reader.Name);
break;

case "xref":
_reader.Read();
Entries[_entryCnt].Last_sense.Add_xref(_reader.Value);
break;

case "ant":
_reader.Read();
Entries[_entryCnt].Last_sense.Add_ant(_reader.Value);
break;

case "field":
_reader.Read();
Entries[_entryCnt].Last_sense.Add_field(_reader.Name);
break;

case "misc":
_reader.Read();
Entries[_entryCnt].Last_sense.Add_misc(_reader.Name);
break;

case "s_inf":
_reader.Read();
Entries[_entryCnt].Last_sense.Add_s_inf(_reader.Value);
break;

case "gloss":
// read attribs
_tmp = "en"; // default language
while (_reader.MoveToNextAttribute())
{
switch (_reader.Name)
{
case "g_lang":
_tmp = _reader.Value;
       break;
}
}

_reader.Read();
Entries[_entryCnt].Last_sense.Add_gloss(_reader.Value, _tmp);
break;
}
break;
}
}

// alright
return "";
}
catch (Exception ex)
{
// return error description
return errString(ex);
}
finally
{
// close reader
_reader.Close();
}
}

public string SaveToXML(string p_filename)
{
StreamWriter _writer;

// open file
try
{
_writer = new StreamWriter(p_filename, false, System.Text.Encoding.UTF8);
_writer.NewLine = "\n";

// write it
try
{
// write it
int _entry;
int _i, _j;
k_ele_data _k_ele;
r_ele_data _r_ele;
info_data _info;
sense_data _sense;
gloss_data _gloss;
for (_entry=0;_entry<Entries.Length;_entry++)
{
// entry begin
_writer.WriteLine("<entry>");
_writer.WriteLine("<ent_seq>{0}</ent_seq>", Entries[_entry].ent_seq);

// kanji
for (_i=0;_i<Entries[_entry].k_ele.Count;_i++)
{
_writer.WriteLine("<k_ele>");
_k_ele = (k_ele_data)Entries[_entry].k_ele[_i];
_writer.WriteLine("<keb>{0}</keb>", _k_ele.keb);
for (_j=0;_j<_k_ele.ke_inf.Count;_j++) { _writer.WriteLine("<ke_inf>&{0};</ke_inf>", _k_ele.ke_inf[_j]); }
for (_j=0;_j<_k_ele.ke_pri.Count;_j++) { _writer.WriteLine("<ke_pri>{0}</ke_pri>", _k_ele.ke_pri[_j]); }
_writer.WriteLine("</k_ele>");
}

// reading
for (_i=0;_i<Entries[_entry].r_ele.Count;_i++)
{
_writer.WriteLine("<r_ele>");
_r_ele = (r_ele_data)Entries[_entry].r_ele[_i];
_writer.WriteLine("<reb>{0}</reb>", _r_ele.reb);
if (_r_ele.re_nokanji) { _writer.WriteLine("<re_nokanji/>"); }
for (_j=0;_j<_r_ele.re_restr.Count;_j++) { _writer.WriteLine("<re_restr>{0}</re_restr>", _r_ele.re_restr[_j]); }
for (_j=0;_j<_r_ele.re_inf.Count;_j++) { _writer.WriteLine("<re_inf>&{0};</re_inf>", _r_ele.re_inf[_j]); }
for (_j=0;_j<_r_ele.re_pri.Count;_j++) { _writer.WriteLine("<re_pri>{0}</re_pri>", _r_ele.re_pri[_j]); }
_writer.WriteLine("</r_ele>");
}

// info
for (_i=0;_i<Entries[_entry].info.Count;_i++)
{
_writer.WriteLine("<info>");
_info = (info_data)Entries[_entry].info[_i];
for (_j=0;_j<_info.lang.Count;_j++) { _writer.WriteLine("<lang>{0}</lang>", _info.lang[_j]); }
for (_j=0;_j<_info.dial.Count;_j++) { _writer.WriteLine("<dial>{0}</dial>", _info.dial[_j]); }
_writer.WriteLine("</info>");
}

// sense
for (_i=0;_i<Entries[_entry].sense.Count;_i++)
{
_writer.WriteLine("<sense>");
_sense = (sense_data)Entries[_entry].sense[_i];
for (_j=0;_j<_sense.stagk.Count;_j++) { _writer.WriteLine("<stagk>{0}</stagk>", _sense.stagk[_j]); }
for (_j=0;_j<_sense.stagr.Count;_j++) { _writer.WriteLine("<stagr>{0}</stagr>", _sense.stagr[_j]); }
for (_j=0;_j<_sense.pos.Count;_j++)   { _writer.WriteLine("<pos>&{0};</pos>",     _sense.pos[_j]); }
for (_j=0;_j<_sense.xref.Count;_j++)  { _writer.WriteLine("<xref>{0}</xref>",   _sense.xref[_j]); }
for (_j=0;_j<_sense.ant.Count;_j++)   { _writer.WriteLine("<ant>{0}</ant>",     _sense.ant[_j]); }
for (_j=0;_j<_sense.field.Count;_j++) { _writer.WriteLine("<field>{0}</field>", _sense.field[_j]); }
for (_j=0;_j<_sense.misc.Count;_j++)  { _writer.WriteLine("<misc>&{0};</misc>",   _sense.misc[_j]); }
for (_j=0;_j<_sense.s_inf.Count;_j++) { _writer.WriteLine("<s_inf>{0}</s_inf>", _sense.s_inf[_j]); }
for (_j=0;_j<_sense.gloss.Count;_j++)
{
_gloss = (gloss_data)_sense.gloss[_j];
_writer.Write("<gloss");
if (_gloss.g_lang != "en") { _writer.Write(" g_lang=\"{0}\"", _gloss.g_lang); }
_writer.WriteLine(">{0}</gloss>", _gloss.translation);
}
_writer.WriteLine("</sense>");
}

// entry end
_writer.WriteLine("</entry>");
}

// ok!
return "";
}
catch  (Exception ex)
{
// return error description
return errString(ex);
}
finally
{
_writer.Close();
}

}
catch (Exception ex)
{
// return error description
return errString(ex);
}

}
#endregion

#region constructor, destructor and serialize
public JMDict()
{
// by default disable throw exceptions
ThrowExceptions = false;
}

/// <summary>
/// Will save current instance of the object into the specified file.
/// </summary>
/// <param name="p_filename">Path and file name.</param>
/// <returns>Error description, or an empty string if no error.</returns>
public string SerializeToFile(string p_filename)
{
try
{
// serialize
FileStream _f = new FileStream(p_filename, FileMode.Create, FileAccess.Write);
BinaryFormatter _b = new BinaryFormatter();
_b.Serialize(_f, this);
_f.Close();

// alright
return "";
}
catch  (Exception ex)
{
// return error description
return errString(ex);
}
}
#endregion

#region static methods
/// <summary>
/// Will return a new JMDict object, created from a previously saved one with
/// a call to SerializeToFile method.
/// </summary>
/// <param name="p_filename">Path and file name.</param>
/// <param name="p_error">Error description, or an empty string if no error.</param>
/// <returns>A new JMDict object.</returns>
static public JMDict DeSerializeFromFile(string p_filename,
                                    ref string p_error)
{
p_error = "";
JMDict _dict = new JMDict();

// deserialize
try
{
FileStream _f = new FileStream(p_filename, FileMode.Open, FileAccess.Read);
BinaryFormatter _b = new BinaryFormatter();
_dict = (JMDict)_b.Deserialize(_f);
_f.Close();

// alright
return _dict;
}
catch (Exception ex)
{
// return error description
p_error = "ERROR: " + ex.ToString();
return null;
}
}
#endregion
}
}


Ejemplo de uso

 // load JMDict
 string _error = "";

 // load JMDict into the object
 JMDict _dict = new JMDict();
 Console.WriteLine("Loading [JMDict]...");
 _error = _dict.LoadFromFile("JMDict");
 Console.WriteLine(_error);


Ahora estoy haciendo la funcion SaveToXML. En un principio queria usar Serializacion, pero con este consumo de memoria el archivo que genera es enorme y el consumo de RAM estratosferico, por lo que al final lo quitare.

pd. El archivo XML en cuestion se puede bajar de aqui;
http://www.csse.monash.edu.au/~jwb/j_jmdict.html
bel Nightroad (a.k.a. Lord Trancos)

AbelNightroad

Estoy haciendo unas pruebecillas y parece que 1.000.000 de strings en un array estatico, ocupan la mitad de RAM que en una StringCollection... asi que lo que creo que voy a hacer es usar un objeto intermedio para la edición y que cuando termine de editar lo convierto un objeto con arrays estaticos.  :roll:
bel Nightroad (a.k.a. Lord Trancos)

Vicente

Hola,

esta tarde en casa lo miro con más calma. Respecto a la serialización, es muy lenta y consume mucha memoria, eso no tiene remedio me temo :(

Un saludo!

Vicente

bnl

¿Como haceis para saber en C# para saber lo que ocupa en memoria un objeto?

¿y  en VB.Net?
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

AbelNightroad

Cita de: "bnl"¿Como haceis para saber en C# para saber lo que ocupa en memoria un objeto?

¿y  en VB.Net?

Ni idea, yo solo miraba el Administrador de Tareas para ver cuanta memoria ocupaba el programa.
bel Nightroad (a.k.a. Lord Trancos)

bnl

Eso te puede dar una idea aproximada, pero tampoco es muy fiable. Sabes que el garbage colector no es determinista y puede recuperar memoria en momentos diferentes.
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

AbelNightroad

Cita de: "bnl"Eso te puede dar una idea aproximada, pero tampoco es muy fiable. Sabes que el garbage colector no es determinista y puede recuperar memoria en momentos diferentes.

No se si servira de algo, pero hacia un GC.Collect justo antes de comprobar la memoria. De todos modos, al final he hecho lo de los arrays estaticos y ahora el programa solo me chupa 100Mb. Cuando quiera poder editar un objecto, lo convierto en uno editable, lo modifico y lo vuelvo a convertir en un de tamaño fijo.  :D
bel Nightroad (a.k.a. Lord Trancos)

vincent

Puedes utilizar PerformanceCounters. Aqui tienes un poco de información:
http://zamov.online.fr/EXHTML/CSharp/CSharp_927308.html
Desarrollo en .Net y metodologías http://devnettips.blogspot.com

Vicente

Hola,

la verdad que incluso 100MB me parece mucho (calculando que tienes según dices unos 20.000.000 de objetos y tal). Pero bueno, ya parece una cantidad más aceptable.

He estado mirando el código y no veo nada raro, lo único que probaras List<String> en vez StringCollection, pero List<String> seguro que es más pesado que un String[]...

El proyecto por cierto tiene una pinta muy curiosa :) (estuve viendo la web que linkaste).

Por cierto, para saber el tamaño de un objeto, no se puede de forma manejada creo. Se puede serializar en memoria y ver su tamaño serializado, pero te da algo que es más grande que el objeto original. En unsafe me parece que había algo, pero no estoy seguro...

Un saludo!

Vicente

AbelNightroad

Si, es mucha RAM, pero me parece una cantidad "asumible" para mi proyecto en cuestion. Ademas, eso es cargando completamente el archivo, con el código que tengo, siempre puedo realizar un carga parcial del mismo (que será lo habitual).

vincent; interesante lo de los PerformanceCounters.

Ahora tengo otra duda, esta vez respecto al uso de c# como lenguaje script. He estado mirando documentos sobre el tema y ya se como llamar a un metodo y pasarle parametros, pero no se como leer el resultado que devuelve ese metodo, o leer propiedades.


MethodInfo m = type.GetMethod("MetodoQueDevuelveUnaString");

string[] myArgs;
myArgs = new string[1];
myArgs[0] = "parametro";

m.Invoke(o, myArgs);


el objeto MethodInfo tiene una propiedad ReturnType, e imagino que sera por ahi por donde tengo que "atacar", pero no encuentro la forma de lograr leer la string que devuelve el metodo...  :?
bel Nightroad (a.k.a. Lord Trancos)

zupervaca

Hace tiempo hice un sistema pequeñito de plugins para probar el enlace dinamico en csharp, el codigo es este:

using System;
using System.Reflection;

namespace Plugin
{
   /// <summary>Permite leer plugins</summary>
   public class Plugin
   {
       #region Metodos

       /// <summary>Constructor</summary>
       /// <param name="pluginName">Nombre del plugin</param>
       public Plugin(string pluginName)
       {
           this.Assembly = System.Reflection.Assembly.LoadFrom(pluginName);
           this.AssemblyName = this.Assembly.GetName().Name;
       }

       /// <summary>true indica que ha sido creado, false que no</summary>
       public bool IsCreated
       {
           get
           {
               return this.Assembly != null ? true : false;
           }
       }

       #endregion

       #region Propiedades

       /// <summary>Ensamblado del plugin</summary>
       readonly public Assembly Assembly;

       /// <summary>Nombre del ensamblado</summary>
       public string AssemblyName;

       #endregion

       #region Clases

       /// <summary>Controla una clase de un plugin</summary>
       public class Class
       {
           #region Metodos

           /// <summary>Crear la clase de un plugin</summary>
           /// <param name="plugin">Plugin</param>
           /// <param name="nameClass">Nombre de la clase</param>
           public Class(Plugin plugin, string nameClass)
           {
               string fullNameClass = plugin.AssemblyName + "." + nameClass;
               this.Object = plugin.Assembly.CreateInstance(fullNameClass);
               this.Type = plugin.Assembly.GetType(fullNameClass);
           }

           /// <summary>Llamar a un miembro de la clase</summary>
           /// <param name="member">Nombre del miembro</param>
           /// <param name="args">Argumentos</param>
           /// <returns>Objeto devuelto por el miembro</returns>
           public object Invoke(string memberName, object[] args)
           {
               return this.Type.InvokeMember(memberName, BindingFlags.Default | BindingFlags.InvokeMethod, null, this.Object, args);
           }

           /// <summary>true significa que la clase ha sido creada, false que no</summary>
           public bool IsCreated
           {
               get
               {
                   return this.Object == null || this.Type == null ? false : true;
               }
           }

           #endregion

           #region Propiedades

           /// <summary>Clase</summary>
           readonly object Object;

           /// <summary>Tipo de la clase</summary>
           readonly Type Type;

           #endregion
       }

       #endregion
   }
}



La clase Plugin enlaza dinamicamente una libreria externa a la aplicacion y la clase Plugin.Class permite su control.
Lo correcto es derivar de la clase Plugin.Class o hacer un interfaz de ella para ocultar asi las llamadas con Invoke.

Jare

Cita de: "Vicente"la verdad que incluso 100MB me parece mucho (calculando que tienes según dices unos 20.000.000 de objetos y tal).
5 bytes por objeto no parece mucho, teniendo en cuenta que la zona de memoria de cada objeto tiene que incluir información de gestión de memoria, de garbage collection, y sus propios datos. ;)

Vicente

Hola,

Lord Trancos:

el método invoke devuelve un object. Ese object es el resultado de la llamada de tu método. Con ReturnType sacas el tipo real de ese object. Era eso lo que querías no?

Jare:

corramos un tupido velo, mejor no digo lo que me había dado dividir 100 millones entre 20 millones... :oops: La verdad, que visto así, 100 MB ahora me parecen pocos.

Un saludo!

Vicente






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.