Você está na página 1de 91

Capitulo 1

Tipor por valor --> Stack Existen 3 tipos por valor: - Tipos pre-construidos Son los que nos otorga .Net - Definidos por el usuario Son tambin llamados estructuras, son una composicin de varios tipos por valor. Ejemplos: Point(tiene X e Y). La instancia de las estructuras dependen de sus campos.Se deben utilizar cuando: - Su instancia es menor a 16 bytes. - Lgicamente representan un valor - No se va a modificar luego de su creacin - No va a castear a un tipo por referencia

- Enumerados Todos estos heredan de System.Value que es el tipo base Para puntos flotantes, el double es el mejor, debido a que es optimizado por hardware. System.Object posee el mtodo ToString Los tipos por valor, pueden funcionar como objetos, pues tienen mtodos. Tipos por valor poseen un constructor implcito, el cual le asigna a la variable un valor por default (como 0 o null), pero es recomendable asignarle un valor inicial. Para verificar si a una variable se le ha asignado un valor o no, se puede utilizar algo as bool? b = null Lo cual le asigna un valor diferente a los que normalmente puede tener la variable. Y luego para saber si es que a la variable se le ha asignado un valor, se puede utilizar hasValue.

-----------------------------------------------------------------------Tipos por referencia

Almacenan la direccin de la ubicacin de su data. Su data es almacenada en el heap. Garbage Collection administra la memoria utilizada por el heap. Los tipos por referencia ms comunes son: - Object - String - StringBuilder - Array - Stream - Exception Los tipo System.String son inmutables, es decir, no se pueden modificar, cada vez que se le cambia el valor, abandona su antiguo valor y crea un nuevo System.String Para evitar esto, se puede utilizar los mtodos de System.String como Concat, Join o Format. O tambin se puede utilizar StringBuilder que permite crear cadenas dinmicas. La clase System.String es bastante caractersticas pues sobreescribe muchos operadores de Object, como: +, ==, !=, =. La forma de utilizar un array, es de la siguiente forma: int [] arreglo = {1,3,5}; Array.sort(arreglo) Stream es utilizado para la lectura y escritura desde disco o alguna parte de la red. Los stream de redes tienen un namespace llamado System.Network.Sockets. Mientras que los stream encriptados se encuentran en System.Security.Cryptography. FileStream es utilizado para lectura y escritura de archivos. MemoryStream es utilizado para leer y escribir de memoria. StreamReader lee data desde un stream StreamWriter te permite leer data desde un stream Al momento de pasar al constructor, de estos 2 ltimos Stream, un archivo, ste queda abierto para su modificacin. Es conveniente el terminar la lectura o escritura del archivo con un close, para que no permanezca bloqueada. Para customizar una excepcin, uno debera heredar de la clase System.ApplicationException. El ordenar los catch de acuerdo al tipo de excepcin, muchas veces es llamado filtering exception. En finally, normalmente se coloca cdigo para cerrar un archivo, limpiar un objeto, entre otros. IMPORTANTE!!!. El finally no puede acceder a variables que se encuentran declaradas dentro del bloque try catch.

-------------------------------------------------------------------------Clases Toda clase est compuesta de mtodos y propiedades. Herencia La herencia nos permite heredar del padre, muchas propiedades y mtodos tiles, los cuales, incluso, podemos sobreescribir, es decir, si es que mi clase hereda ToString, puedo sobreescribir este mtodo, para que en el momento en que se imprima mi clase, imprima lo que yo deseo. Interfaces Poseen un conjunto de mtodos y propiedades, que todos aquellos que hereden de sta deberan de implementar. Los mtodos en las interfaces no pueden explicitar si son pblicos, protected o privados; esto se especifica en la clase que lo implementa. Una interfaz puede llegar a heredar de otra interfaz. Generics Permiten definir un tipo sin especificar detalles. Para casos como Collections permite optimizacion, pues manejar lista de objetos especficos, es ms ptimo que trabajar con lista de Objects que debes de castear cada vez que los obtienes. Otra ventaja que nos ofrece, es que reduce la cantidad de errores en tiempo de ejecucin por problemas de casteo. Los generics no pueden utilizar operadores como "+" o ">", pues se limita bastante a las capacidades de la clase Object. Soportan 4 tipos de constraint: - Interface.- Permite solo tipos que implementen interfaces especficas para usar tus generics. - Base class.- Permite solo tipos que concuerden o hereden de una clase base especfica para usar tu generic. - Constructor.- Requiere tipos que usen tu generics para implementar un constructor menos parametrizado. - Reference or value type.Ejemplo: class CompGen<T> where T : IComparable{ .... } Esto quiere decir que el parmetro solo pueden ser aquellos tipos que implementen IComparable. Evento Es la ocurrencia de una accin, la cual pudo ser causada por una interaccion, un click de mouse, o puede ser hecha por otro programa.El object que levanta el evento es llamado el event sender, mientras que el objeto que captura el evento, es llamado receptor de evento (event receiver). Un evento se puede levantar con: public event MyEventHandler MyEvent;

MyEventHandler handler = MyEvent; EventArgs e = new EventArgs(); handler(this, e); Delegado Es un puntero de una funcin. Muchas veces es utilizado para sealar un evento a un objeto. Para utilizarlo, se debe de asociar el evento con el manejador del evento. Atributos Describen tipos, mtodos o propiedades que pueden ser consultadas programaticamente usando Reflexion. Sus usos ms comunes son: - Especificar qu privilegios de seguridad requiere una clase - Especificar privilegios de seguridad que permitan reducir el riesgo de seguridad. - Declarar capacidades, tales como soportar serializacion. - Describir el assembly con un ttulo, descripcin o notificacin de copyright. Derivan de System.Attribute y son especificadas usando [] . Para permitir que una clase sea serializable se le debe aadir [Serializable], por ejemplo: [Serializable] clas MiClase{ //Some code here } Type Forwarding es un atributo que permite mover un tipo a de un assembly, a otro assembly, de tal forma que no se deba recompilar los clientes que consuman el primer assembly. Solo funciona con componentes referenciados por apliaciones existentes.Ejemplo: [assembly:TypeForwardedTo(typeof(DestLib.TypeA))]

-----------------------------------------------------------------------------------Lesson 4 widening conversion --> Cuando se convierte de un tipo de menor precision a uno de mayor precisin de forma implcita. Ejemplo: De int a double. narrowing conversion --> Cuando se convierte de un tipo de mayor precisin a uno de menor precisin. Formas de realizar conversiones: - System.Convert, entre tipos que implementan IConvertible - type.ToString - type.Parse

- type.TryParse y type.TryParseExact, convierte de string a un tipo base, retorna false si no es posible. Narrowing conversion falla si es que el valor que se va a convertir excede el tamao del tipo al que se va a convertir. Se deben de tratar estas conversiones con bloques de try-catch. Boxing es transformar un tipo por valor a un tipo por referencia. Ejm: int a object. Unboxing es transformar un tipo por referencia a un tipo por valor. Ejm: object a int. Recomendaciones: - Mejor tener varios mtodos con sobrecargas, que uno solo con parmetro object. - En lo posible utilizar generics - Sobre escribir ToString, Equals y GetHash Las formas de conversion de los tipos personalizados son: - Definir operadores de conversin para simplificar las conversiones de tipos numricos. - Sobre escribir ToString. - Implementar System.IConvertible - Implementar TypeConverter para conversiones a nivel de programa. Se utiliza implicit como palabra clave cuando no se va a perder precisin. Y explicit para cuando s se va a perder. La forma de convertir mi custom type, luego de haber implementado el IConvertible es de la siguiente forma: b = Convert.ToBoolean(a);

Captulo 2

Input/Output Lesson 3 Compressing Streams Me puede ser til cuando quiero utilizar con eficiencia el ancho de banda, el almacenamiento, etc. GZIP y DEFLATE son estndar en industrias. son algoritmos de compresin. Pueden comprimir data de un mximo de tamao de 4GB. Los streams que implementan estos algoritmos son: GZipStream y DefalteStream. Length, Position, Seek y SetLength arrojan una excepcin en la clase GZipStream y DeflateStream CompressionMode.Compress indica que se va a comprimir, tb puede indicarse que se va a descomprimir.

Lesson 4: Trabajando con almacenamiento aislado (storage isolated) Es muy til el reservar la informacin en un espacio reservado sin tener problemas de si la aplicacin tiene derechos para grabar en el disco duro o no. IsaolatedStorageFile, permite crear archivos y directorios en el isolated storage. IsolatedStorageScope es un enumerator que describe el scope del isolated storage Antes de grabar data en tu isolated storage, se debe de determinar cmo alcanzar la data que t quieres guardar. Se puede elegir entre 2 mtodos: - Assembly/Machine.- Crea un almacenamiento para llamadas del assembly y de la mquina local. Ideal para crear data a nivel de aplicacin. Se hace de la siguiente forma: IsolatedStorageFile machineStorage = IsolatedStorageFile.GetMachineStoreForAssembly(); - Assembly/User.- Crea un almacenamiento relacionada con el assembly y el usuario actual. Es til para crear data a nivel de usuario. IsolatedStorageFile machineStorage = IsolatedStorageFile.GetUserStoreForAssembly(); Existe un nivel de aplicacin utilizado SOLO para Click-once.

IsolatedStorageFileStream, es un stream utilizado para crear archivos en el isolated storage.

IsolatedStorage no puede verificar si un archivo existe ah, como lo hace el File.Exists. Si se intenta crear un archivo en un directorio que no existe, se lanza un path-parsing exception. IsolatedStorageFilePermission encapsula los permisos que especifican el acceso al isolated storage. UsageAllowed es para los tipos de permisos a los usuarios. UserQuota es el tamao de almacenamiento mximo por usuario. Para otorgar suficientes permisos, uno necesita demandar o pedir permisos. Para hacer que el framework se encargue de esto, se hace lo siguiente: [IsolatedStorageFilePermission(SecurityAction.Demand)] class .... Esto permite seleccionar qu assemblies requieren permisos, y si no los tiene, con este atributo, hace el pedido.

Capitulo3
Searching, Modifiyin and encoding text Lesson 1 ^\d{5}$ es una expresin regular. Significa ^ Comienzo del string, si es multilnea, va a matchear con cada lnea $ fin del string, si es multilinea, va a matchear con cada lnea \d significa digitos numricos {5} significa que debe haber cinco digitos numricos secuenciales. Las expresiones regulares son muy tiles para filtrar el input del usuario. \b para cuando es la nica palabra o termina en esa palabara \B cuando es la unica palabra o comienza con sta. \A es parecido como el ^ pero solo para la primera lnea \Z lo mismo k $ pero solo de la linea antes del caracter \n \z lo mismo k $ pero solo de la ltima lnea. \G especifica que el match ocurre desde el punto donde el previo match fue hecho. \a bell alarm \b fuera de expresiones regulares, significa un backspace Se puede hacer uso de *, por ejemplo to*n puede matchear ton, toon, tn to+n puede matchear ton, toon, pero no tn to{3}n matches tooon, pero no ton o tn to{1,3}n matches ton, tooon, pero no tn o toooon.

Se puede colocar solo mnimo as: to{1,}n El simbolo ? vuelve a un caracter opcional. el simbolo "." reemplaza a cualquier caracter. [simbol] ac dentro van los caracteres permitidos en esa posicin. O tb puede ir un rango de caracteres. \D representa a cualquier caracter no numrico (x|y) va a elegir entre x o y para referir a la matcheada data, se puede usar (?<name>pattern) (?<char>\w)\k<char> sirve para encontrar palabras donde tengan 2 letras consecutivas iguales, como: small, will, llama, etc. (?<char>\s\w+)\k<char> verifica palabras completas, repetidas, que se encuentren backreference se refiere a la ms reciente captura. ()\l matches empty string En el constructor de Regex se pueden especificar opciones a las expresiones regulares, usando RegexOptions (es un enumerador) En opciones el "-" significa "apagar" una opcin. Todas las opciones estn apagadas por default. ECMAScript puede ser usado solo con IgnoreCase y Multiline flags CultureInvariant indica que la diferencia cultural entre lenguajes es ignorado Regex.Replace te permite reemplazar un input de un formato a otro. Lesson 2 Encoding and Decoding El tema a tratar es sobre que las cadenas tienen diferente codificacin. ASCII al inicio no incluia caracteres que no estaban en el alfabeto ingls. ANSI tuvo una solucin para este problema y utilizo del 0 al 127 los codigos ASCII y los dems para otros valores especficos. framework de .Net utiliza Unicode UTF-16 System.Text incluye las siguientes codificaciones: - UTF-32.- Utiliza UTF32Encoding para convertir desde y hacia un UTF32 - UTF-16.- Utiliza UnicodeEncoding para convertir desde y hacia un UTF-16 - UTF-8.- UTF8Encoding - ASCII.- Codifica el alfabeto latino. Utiliza ASCIIEncoding

- ANSI/ISO.- Encoding Encoding.GetEncoding devuelve un objeto encoding para una especificada codificacin. GetBytes convierte un UNICODe string a su representacin en bytes en una codificacin especificada. Encoding.GetEncodings obtiene un arreglo de EncodingInfo que soporta el framework. Captulo 4 Collections y Generics Lesson 1 Los dictionary sirven para colecciones pequeas, en cambio los hashtable sirven para cuando la coleccin es muy grande. Una manera hbrida de hacer esto es el HybridDictionary ArrayList es un arreglo desordenado que puede almacenar cualquier tipo de objeto.Sus mtodos importantes son Add y AddRange. el AddRange puede soportar adherir un arreglo de cualquier objeto que soporte la interface ICollection (todos los arreglos implementan esto). Adems tiene los mtodos insert e insertRange que permiten insertar en la posicin que uno desee. Aparte permite el uso de indexacin, para ubicar objetos o extraerlos de ste. Remove, remueve un objeto especfico. No arroja excepcin RemoveRange, remueve un rango de indices. RemoveAt, remueve un ndice especfico. ArrayList implementa la interface IEnumerator e IEnumerable. Icollection soporta s o s IEnumerable, su propsito es que toda coleccin soporta una forma comn de obtener items de una coleccin, as como copiar la coleccin a un array. IList soporta ICollection e IEnumerable. El mtodo Sort de un ArrayList sirve para ordenar los items. esto usa la interfaz IComparer. Se puede especificar el tipo de comparacin como: coll.Sort(new CaseInsensitiveComparer()); Comparer es una implementacin por default de IComparer Para

Lesson 2 la clase Queue soporta FIFO, manejando de forma secuencial los objetos. Mtodos importantes de Queue: Dequeue = Obtienes el primer elemento de la cola, removindolo Enqueue = adhiere un item al final de la cola Peek =obtiene el primer elemento de la cola, sin removerlo. Queue permite agregar valores duplicados o incluso valores nulos. La forma de comprobar si una cola est vaca es con Count.

la clase Stack soporta LIFO. Sus mtodos ms importantes son: Pop obtiene el item del tope del stack y lo remueve Push, adhiere un item al tope del stack. Peek obtiene el item del tope del stack, pero no lo remueve.

Lesson 3 la clase Dictionary es usada para mapear de la forma key/value. Otro tb conocido es el HashTable que hace lo mismo. ejemplo para adherir elementos a uno de estos es: tabla.add("yo@email.com", "christian palomares"); o sino: tabla["yo@email.com"] = "Christian Palomares"; Para iterar sobre un hashtable o dictionary, se debe de hacer de la siguiente forma: foreach (DictionaryEntry entry in tabla) { Console.WriteLine(entry.Value); } Un DictionaryEntry contiene un Key y un Value asociado. Todas las clases diccionarios (tb el HashTable), soportan la interface IDictionary (deriva de ICollection). Sus propiedades importantes son: Keys .- Devuelve un ICollection con la lista de los keys Values.- Devuelve un ICollection con la lista de los values Contains verifica si una especfica key est en el diccionario GetEnumerator devuelve un IDictionaryEnumerator Remove, remueve un item con una especfica key. una forma de iterar sobre los valores sera: forach(object name in tabla.Values){ Console.WriteLine(name); } HashTable tiene 2 mtodos particulares: ContainsKey, verifica si la coleccin contiene una llave especfica ContainsValue, verifica si la coleccin contiene un valor especfico En un HashTable no se puede tener 2 entrys con el mismo key, pues si entra un 2do, reemplaza el valor del primero. El comparador que va a utilizar el HashTable, se le pasa como parmetro a su constructor. Cuando uno itera sobre el hashtable, estos estn ordenados por su valor hash(hashvalue). SortedList, a diferencia de HashTable, s soporta ordenamiento, pues al ingresar un nuevo entry, ste entra ordenado.

Su propiedad Capacity, devuelve la cantidad de slots para los items, NO DEVUELVE EL NMERO DE ITEMS EN LA COLECCIN. Permite el uso de ndices, as como mtodos como GetByIndex. Se le puede especificar un IComparer al SortedList, en su constructor. De tal forma que puede ordenar de una forma particular, por ejemplo descendiente. Diccionarios especializados: ListDictionary es bueno cuando son pocos elementos, a comparacin del hashtable que es bueno cuando son muchos. HibrydDictionary es cuando uno no conoce el tamao de su arreglo y desea hacerlo de forma eficiente. OrderedDictionary, es como un HashTable pero ordenado, y de una forma particular que uno desee. Tiene como propiedades: Item, para acceder a cierto ndice. Y como mtodos Insert, para insertar en cierto ndice un key/value. RemoveAt, remover tal elemento en tal ndice.

Lesson 4 BitArray es una coleccin resizable (no dinmica) que puede almacenar Boolean values. Aparte, soporta operaciones a nivel de bits como and, not, or, Xor. BitVector32 permite manipular bits en un integer de 32 bits. No es dinmica (no vara su tamao), tiene un tamao fijo de 32 bits que pueden ser manipulados de forma individual.

BitArray no soporta Add o Remove, su tamao se le indica en su contructor y luego se puede modificar con su propiedad length. Al inicio de la instancia, los valores estn en false. Para realizar operaciones entre arreglos, se hace lo siguiente: lista1.operacion(lista2) como el siguiente: lista1.Xor(lista2) que devuelve otro BitArray BitVector32 es una estructura muy til para administrar bits individuales. Su propiedad Data devuelve el valor del integer de 32 bits. tiene un mtodo esttico llamado CreateMask que es secuencial. Por ejemplo, para setear el valor de los 2 primeros bits, se hara un CreateMask sin parmetros, mientras que se llama una segunda vez con parmetro la anterior mscara. Luego se setea a true para tener el valor de 3. Entonces se puede obtener su valor as. vector[firstBit] vector[secondBit]

Tb permite usar toda su capacidad para almacenar varios nmeros pequeos. BitVector32.Section firstSection = BitVector32.CreateSection(10); BitVector32.Section secondSection = BitVector32.CreateSection(50, firstSection); BitVector32.Section thirdSection = BitVector32.CreateSection(500, secondSection); Entonces para almacenar valores se puede usar vector[firstSection] = 10; vector[secondSection] = 1; vector[thirdSection] = 192; y escribirlos as Console.WriteLine(vector[thirdSection]); Ya que el uso comn de los arreglos es String, se tiene una coleccin especializada para esto: StringCollection y StringDictionary StringCollection es una coleccin dinmica que solo puede almacenar strings. Su uso es igual al de ArrayList StringDictionary es igual a Dictionary, solo que ahora el key y el value son string. Es case insensitive. CollectionsUtil.CreateCaseInsensitiveHashtable(); y CollectionsUtil.CreateCaseInsensitiveSortedList() Son para crear hashtables y sortedList que no sean case sensitive La comparacin es dependiente de la cultura actual. En muchos casos de aplicaciones web, se debera hacer que la coleccin no se vea afectada por la cultura. Para esto se utiliza el StringComparer: Hashtable hash = new Hashtable(StringComparer.InvariantCulture), lo mismo para SortedList NameValueCollection solo permite strings. Permite mltiples valores por key, as como tambin se puede buscar los elementos por ndice o key. lista.Add("key","Some text") lista.Add("key","More text") foreach(string s in lista.GetValues("key")){ Console.WriteLine(s); Si uno adhiere de la forma lista["key"], solo guarda un valor. Si uno coloca Console.WriteLine(lista["key"]), devuelve los valores separados por coma.

Lesson 5 Entre las listas genricas (type-safe) que se tienen en .net, se pueden encontrar List<>, LinkedList<>, Dictionary<>, Queue<>, Stack <>, SortedList<> y SortedDictionary<>. Los Dictionary<> retornan un KeyValuePair, ya no retornar un dictionary entry.

Capitulo 5
Serializacin Representar un objeto en un diferente formato. Es el proceso de serializar y deserializar objetos que son transferidos y luego reconstruidos. Se convierte el objeto en una secuencia lineal de bytes. Pasos para serializar objetos: 1. Crear un stream donde se almacenar el objeto serializado. 2. Crear un BinaryFormatter 3. Llamar al mtodo Binaryformatter.Serialize para serializar el objeto y colocar el resultado en el stream. En el mtodo serialize, se le pasa como primer parmetro el Stream y como segundo el objeto a serializar Para el proceso de deserializacion se siguen los sgtes pasos: 1. Crear un stream para leer el objeto serializado. 2. Crear un BinaryFormatter 3. Crear un nuevo objeto donde almacenar lo deserializado. 4. llamar al mtodo BinaryFormatter.Deserialize y castearlo al tipo correcto. Para que una clase hecha por nosotros sea serializable, se debe de colocar [Serializable] como atributo, esto serializa todo, incluso miembros privados. Si se desea que uno de los atributos no sea serializable, se le coloca al costado [NonSerialized] public int total; Si es que ese total proviene del calculo de otros elementos, en el proceso de deserializacion, no va a ser inicializado, pero si necesitamos que se calcule antes de que el objeto sea deserializado. Para esto debemos hacer que nuestra clase implemente la interfaz IDeserializationCallback, el mtodo OnDeserialization(Object sender), el cual se llamar en el momento que el objeto se deserialize.

Para el control de versiones de la aplicacion Se puede utilizar OptionalField que no afectar el proceso de deserializacin. Si es que en el proceso de deserializacin el miembro no fue serializado, el valor ser dejado en null sin arrojar excepcin. [OptionalField] Mejores prcticas para compatibilidad de versiones: - Nunca remover un campo serializado. - Nunca aplicar NonSerializedAttribute a un atributo que lo era en una versin previa. - Nunca cambiar el nombre o tipo de un campo - Si se adhiere un nuevo atributo, colocarle OptionalFieldAttribute - Si se remueve el atributo NonSerializedAttribute, colocarle OptionalFieldAttribute - Para los atributos opcionales, inicializar sus datos en Serialization callback. BinaryFormatter es el formato en binario que se le da a nuestros objetos, se debera usar cuando uno conoce que todos los clientes a los que va a transferir el binario, tienen aplicaciones en .net framework. SoapFormatter formatea los objetos en xml, la cual es la forma ms confiable de transferir datos, pues es muy til para el caso de XML. Debido a que es un xml, ser abierto por cualquier aplicacin. Se debe utilizar cuando se requiere portabilidad. Debido a su complejidad, es menos eficiente que el BinaryFormatter. La forma de formatear con SoapFormatter es muy parecido a la de BinaryFormatter, solo se substituye la clase BinaryFormatter por SoapFormatter, aunque el archivo resultante es muy diferente. Para controlar el formateo de SOAP, se puede aadir algunos atributos como: SoapAttribute para sealar que el atributo va a ser serializado SoapElement para seaalr que la clase va a ser serializada como un elemento XML. SoapEnum, para enumeradores SoapIgnore, para no considerar este campo al momento de la serializacin SoapInclude, cuando este tipo debe ser incluido cuando se generan esquemas. Se debera deshabilitar la serializacin para elementos que son calculados o temporales. Se debera colocar como serializable clases que incluso no se serializarn en ese momento, pues en un futuro se pueden necesitar.

Lesson 2 XML provee un estndar que puede ser ledo por las computadoras. Se pueden almacenar imgenes, msica, archivos binarios, e incluso informacin de base de datos. Se puede usar TextWriter o XmlWriter. Serializacion en XML se debera de utilizar cuando se necesita intercambiar un objeto con una aplicacin que no est basada en el framework .Net. Ofrece: - Interoperabilidad - Administracin amigable - Provee archivos ms fciles de leer Limitaciones: - Solo puede serializar datos pblicos, no privados. - No se pueden serializar grafos. Para serializar como xml una clase creada por nosotros, debemos de seguir los siguientes pasos: - Especificar la clase como pblica - Especificar todos los miembros que se desean deserializar como pblicos - Crear un constructor sin parmetros La clase no necesita tener el atributo Serializable para poder ser serializado como XML Una clase que no tiene ningun atributo para la serializaion en XML, se serializara a XML donde cada uno de sus miembros es un elemento XML, por ejemplo: <?xml version="1.0" ?> <Clase> <att1>valor</att1> <att2>otrovalor</att2> </Clase> El atributo XmlRoot("nombre"), sirve para especificar con otro nombre serializado a la clase que se piensa serializar. XmlIgnore permite ignorar un atributo para que no sea serializado (como [NonSerialized]). XmlAttribute permite que el campo, se vuelva un atributo en el momento de la serializacion, es decir estar de la siguiente forma <Clase att1 = "valor"> ..... </Clase> Uno puede tomar control sobre la serializacin en XML, implementando la interfaz IXmlSerializable e implementando sus mtodos ReadXml y WriteXml para controlar el XmlReader y XmlWriter. XSD = XML Schema Definition

xsd.exe permite generar un esquema personalizado o estndar(como clase) para las clases que se piensan serializar. Las instancias de DataSet pueden ser serializadas a XML. Se serializa de la misma forma que cualquier otro objeto, pero no provee un control de lectura que debera de tener. De forma alterna, se puede utilizar DataSet.WriteXml, DataSet.ReadXML y DataSet.GetXml Lesson 3 Cuando se desea hacer una serializacin customizada, se debe de implementar la interfaz ISerializable, adems que se debe de tener un constructor para el proceso de serializacin, el cual recibe como parmetros: SerializationInfo info, StreamingContext context. del SerializationInfo es de donde se obtienen los datos de la forma info.GetInt32("precio") OnSerializing antes de que se serialize OnSerialized despus de la serializacin OnDeserializing antes de que se d la deserializacin OnDeserialized despus de la deserializacin y del OnDeserialization Estos eventos reciben como parmetro un StreamingContext. Se puede aplicar el mismo evento a ms de un mtodo, o aplicar un solo mtodo a varios eventos. Estos 4 eventos solo se realizan en la serializacin binaria, no en SOAP ni en la customizada. StreamingContext tiene 2 propiedades importantes: - context.- Es una referencia a un objeto que posee la informacin deseada por el usuario. - State.- Es una serie de bits que funcionan como flags, pueden indicar: -CrossProcess.- La fuente o destino es un diferente proceso en la misma mquina. -CrossMachine.- La fuente o destino est en una diferente mquina -File.- La fuente o destino es un archivo -Persistence.- La fuente o destino es una base de datos, un archivo u otro. -Remoting.- La fuente o destino es remota a un sitio desconocido. -Other.- La fuente o destino es desconocida. -Close.- El objeto grafo est siendo clonado. -CrossAppDomain.- La fuente o destino es un diferente AppDomain. -All.- Es un contexto por default Este streaming context se analiza cuando se implementa el ISerializable

Cuando uno construye su formateador, ste automticamente setea su Context a null y su State a All. Para crear un Custom Formatter, implementa la interfaz IFormatter o IGenericFormatter. El BinaryFormatter y SoapFormatter implementar la interfaz IFormatter. FormatterServices provee mtodos estticos para ayudar con la implementacin del Formatter.

Capitulo 6
El namespace System.Drawing permite crear graficos o modificar imgenes. Cambiar de tamao una imagen, crear crculos, lneas u otras formas, zoom a imgenes, adherir copyright a logos o textos, etc. La clase Graphics es la ms utilizada de stas. Pen es utilizada para dibujar lneas Mientras que las clases derivadas de la clase Brush son utilizadas para llenar algunos interiores o formas. PictureBox es utilizado en los windows forms para mostrar imgenes como parte de la interfaz. Para especificar la posicin de un control Windows Forms, se debe de utilizar su propiedad Location, y para esto, se le debe de asignar un punto, es decir, se utiliza la clase Point de la siguiente forma. button1.Location = new Point(110,25); Aunque tb se puede especificar seteando las propiedades Left y Top del control: button1.Left = 110; button1.Top = 25; Para especificar el tamao del control, se le puede especificar una clase Size, a su propiedad Size. button1.Size = new Size(30,30); Para modificar los colores de un control, puedes utilizar la estructura Color de la siguiente forma: button1.ForeColor= Color.Red; button1.BackColor= Color.Blue; Si es que se necesita especificar un color customizado, se puede utilizar Color.FromArgb(), de la siguiente forma: button1.ForeColor = Color.FromArgb(15,29,67); Para dibujar en un form o en un control, se deben de seguir los sgtes pasos:

1. Crea un objeto Graphics llamando al mtodo system.Windows.Forms.Control.CreateGraphics 2. Crear un objeto Pen 3. Llamar al miembro de Graphics para dibujar en el cotrol, usando el Pen. Una vez creado el objeto graphics, se puede utilizar muchos mtodos para dibujar como: Clear, DrawEllipse, DrawIcon, DrawIconUnstretched, DrawImage, DrawLine, DrawLines, DrawPath, DrawPie, DrawPolygon, DrawRectangle, Drawrectangles y DrawString. En el constructor de Pen, se especifican el color y width en pixeles. Por ejemplo: Graphics g = this.CreateGraphics(); Pen p = new Pen(Color.Red, 7); g.DrawLine(p, 1, 1, 100, 100) dibuja con el Pen que creamos, una lnea desde el punto 1,1 hasta el punto 100, 100. Mtodos como Graphics.DrawLines, Graphics.DrawPolygon, Graphics.DrawRectangles, aceptan arreglos de puntos como parmetros, para dibujar figuras ms complejas. endcap es un final de una lnea, pueden ser utilizados para crear flechas. Por default, el Pen dibuja lneas slidas. Por ejemplo, para crear un Pen que dibuje lneas punteadas, se debera de setear la propiedad de Pen.DashStyle a uno de los siguientes valores: DashStyle.Dash, DashStyle.DashDot, DashStyle.DashDotDot, DashStyle.Dot o DashStyle.Solid. Adems de estos, se puede utilizar Pen.DashOffset y Pen.DashPattern para definir customizados patrones dash(guion). Para crear flechas, uno debe de modificar las propiedade Pen.StartCap y Pen.EndCap, utilizando el enumerador LineCap, el cual tiene valores como: LineCap.ArrowAnchor LineCap.DiamonAnchor LineCap.SquareAnchor LineCap.Triangle LineCap.Flat LineCap.Round LineCap.RoundAnchor LineCap.Square La clase Graphics tiene mtodos Fill para dibujar y llenar shapes (formas)

Estos mtodos requieren una instancia de la clase Brush, la cual es abstracta, por lo cual, se debe de instanciar un hijo suyo: System.Drawing.Drawing2D.HatchBrush define un rectangular brush con un estilo hatch System.Drawig.Drawing2D.LinearGradientBrush encapsula un brush con un gradiente lineal. System.Drawing.Drawing2D.PathGradientBrush igual que el anterior, solo que provee un llenado ms complejo System.Drawing.SolidBrush Define un Brush de un color simple. System.Drawing.TextureBrush define un Brush desde una imagen LinearGradientBrush es ms eficiente que PathGradientBrush. Para el llenado, se utilizan mtodos como : g.FillPolygon(b, points); Para llenar un objeto graphics con un simple color, uno debe de llamar al mtodo Graphics.Clear.

Lesson 2 System.Drawing.Image es una clase abstracta que permite crear, cargar, modificar y grabar imgenes, como BMP, jpg o tif. Al ser sta abstracta, uno debe de crear una instancia usando Image.FromFile, el cual recibe como parmetro un path a la imagen, y Image.FromStream, que recibe un System.IO.Stream como parmetro. O tb uno puede utilizar 2 clases que heredan de Image, como : System.Drawing.Bitmap para imgenes. System.Drawing.Imaging.Metafile para imgenes animadas. Los constructores de Bitmap, te permiten crear un Bitmap a partir de un Image, archivo o stream, o sino crear un bitmap blanco con un height y width especificados. Los 2 mtodos ms importantes que tiene son: GetPixel, el cual devuelve un objeto Color, con los colores de ese pixel. SetPixel, setea el color de un pixel. Por ejemplo, para mostrar una imagen, uno debe de utilizar el sgte cdigo: Image i = Image.FromFile(@"c:...."); pictureBox1.BackgroundImage = i o sino Bitmap b = new Bitmap(@"c:...."); pictureBox1.BackgroundImage = b;

Para colocar una imagen como el fondo de un form, se utiliza el sgte cdigo: Bitmap b = new Bitmap("C:...."); Graphics g = this.CreateGraphics(); g.DrawImage(b, 1, 1, this.width, this.height); Para grabar una imagen, el Bitmap usa su mtodo Save Bitmap.Save, el cual recibe como primer parmetro el nombre del archivo y como 2do, el ImageFormat.Jpeg, segun el formato en que uno desee almacenar la imagen. El JPEG es el ms utilizado para fotos El gif es el ms utilizado para charts. Para obtener el Graphics desde una imagen, se hace lo sgte: Graphics g = Graphics.FromImage(bm); Forma simple de usar Icons Graphics g = this.CreateGraphics(); g.DrawIcon(SystemIcons.Question, 40, 40); o tb se puede usar DrawIconUnstretched Para editar un Icon, se debe de llamar al mtodo Icon.ToBitmap, para de esta forma recin editarlo.

Lesson 3 -- Formatting Text Para adherir texto a una image, se debe de realizar lo sgte: 1. Crear un objeto graphics del image 2. Crear un objeto Font 3. Opcionalmente, crear un objeto Brush 4. Utilizar el mtodo Graphics.DrawString y especificar la ubicacin del texto. Para crear un objeto Font, uno puede usar su constructor: Font f = new Font("Arial", 12, FontStyle.Bold) Donde se pasa como parmetros, el nombre de la fuente, el tamao y un FontStyle Aparte, tb se puede utilizar un objeto FontFamily y pasarlo al constructor. FontFamily ff = new FontFamily("Arial"); Font f = new Font(ff, 12); Adems, uno puede hacer lo sgte:

FontConverter converter = new FontConverter(); Font f = (Font) converter.ConvertFromString("Arial, 12pt"); La forma ms simple de pintar un texto en pantalla es: Graphics g = this.CreateGraphics; Font f = new Font("Arial", 40, FontStyle.Bold); g.DrawString("Hola Pitufina", f, Brushes.Blue, 10, 10);

StringFormat te permite configurar el alineamiento y direccion de tu texto. Los miembros ms importantes de StringFormat son: Alignment : StringAlignment.Center centro StringAlignment.Near izquierda StringAlignment.Far derecha FormatFlags: DirectionRightToLeft, texto es mostrado de derecha a izquierda DirectionVertial, es alineado verticalmente DisplayFormatControl FitBlackBox, caracteres que se salen del rectngulo, no son reposicionados LineLimit, permite visualizar todas las lineas. MeasureTrailingSpaces, incluye un espacio al final de cada linea NoClip NoFontFallback, si es que un caracter no es soportado por la fuente que se est colocando, se pone un cuadrado. NoWrap LineAlignment: StringAlignment.Center verticalmente centrado StringAlignment.Near en la parte superior StringAlignment.Far bien abajo Triming, get o set el enumerador String.Trimming, los valores posibles son: Character, el caracter es recortado al caracter ms cercano EllipsisCharacter, el caracter es recortado al caracter ms cercano y una elipse es insertada al final de la linea recortada. EllipsisPath el centro es removido de las recortadas lineas y reemplazadas por una elipse EllipsisWord, especifica que el texto es recortado a la palabra ms cercana y una elipse es insertada la final de la linea recortada None No especifica recorte Word, especifica que el texto es recortado a la palabra ms cercana Para utilizar el dibujar con un StringFormat, se debe de utilizar lo sgte: g.DrawString(cadena, fuente, brush, rectngulo, stringFormat)

Capitulo 7
El namespace System.Drawing permite crear graficos o modificar imgenes. Cambiar de tamao una imagen, crear crculos, lneas u otras formas, zoom a imgenes, adherir copyright a logos o textos, etc. La clase Graphics es la ms utilizada de stas. Pen es utilizada para dibujar lneas Mientras que las clases derivadas de la clase Brush son utilizadas para llenar algunos interiores o formas. PictureBox es utilizado en los windows forms para mostrar imgenes como parte de la interfaz. Para especificar la posicin de un control Windows Forms, se debe de utilizar su propiedad Location, y para esto, se le debe de asignar un punto, es decir, se utiliza la clase Point de la siguiente forma. button1.Location = new Point(110,25); Aunque tb se puede especificar seteando las propiedades Left y Top del control: button1.Left = 110; button1.Top = 25; Para especificar el tamao del control, se le puede especificar una clase Size, a su propiedad Size. button1.Size = new Size(30,30); Para modificar los colores de un control, puedes utilizar la estructura Color de la siguiente forma: button1.ForeColor= Color.Red; button1.BackColor= Color.Blue; Si es que se necesita especificar un color customizado, se puede utilizar Color.FromArgb(), de la siguiente forma: button1.ForeColor = Color.FromArgb(15,29,67); Para dibujar en un form o en un control, se deben de seguir los sgtes pasos: 1. Crea un objeto Graphics llamando al mtodo system.Windows.Forms.Control.CreateGraphics 2. Crear un objeto Pen 3. Llamar al miembro de Graphics para dibujar en el cotrol, usando el Pen. Una vez creado el objeto graphics, se puede utilizar muchos mtodos para dibujar como:

Clear, DrawEllipse, DrawIcon, DrawIconUnstretched, DrawImage, DrawLine, DrawLines, DrawPath, DrawPie, DrawPolygon, DrawRectangle, Drawrectangles y DrawString. En el constructor de Pen, se especifican el color y width en pixeles. Por ejemplo: Graphics g = this.CreateGraphics(); Pen p = new Pen(Color.Red, 7); g.DrawLine(p, 1, 1, 100, 100) dibuja con el Pen que creamos, una lnea desde el punto 1,1 hasta el punto 100, 100. Mtodos como Graphics.DrawLines, Graphics.DrawPolygon, Graphics.DrawRectangles, aceptan arreglos de puntos como parmetros, para dibujar figuras ms complejas. endcap es un final de una lnea, pueden ser utilizados para crear flechas. Por default, el Pen dibuja lneas slidas. Por ejemplo, para crear un Pen que dibuje lneas punteadas, se debera de setear la propiedad de Pen.DashStyle a uno de los siguientes valores: DashStyle.Dash, DashStyle.DashDot, DashStyle.DashDotDot, DashStyle.Dot o DashStyle.Solid. Adems de estos, se puede utilizar Pen.DashOffset y Pen.DashPattern para definir customizados patrones dash(guion). Para crear flechas, uno debe de modificar las propiedade Pen.StartCap y Pen.EndCap, utilizando el enumerador LineCap, el cual tiene valores como: LineCap.ArrowAnchor LineCap.DiamonAnchor LineCap.SquareAnchor LineCap.Triangle LineCap.Flat LineCap.Round LineCap.RoundAnchor LineCap.Square La clase Graphics tiene mtodos Fill para dibujar y llenar shapes (formas) Estos mtodos requieren una instancia de la clase Brush, la cual es abstracta, por lo cual, se debe de instanciar un hijo suyo: System.Drawing.Drawing2D.HatchBrush define un rectangular brush con un estilo hatch System.Drawig.Drawing2D.LinearGradientBrush encapsula un brush con un gradiente lineal. System.Drawing.Drawing2D.PathGradientBrush igual que el anterior, solo que provee un llenado ms complejo System.Drawing.SolidBrush Define un Brush de un color simple. System.Drawing.TextureBrush define un Brush desde una imagen

LinearGradientBrush es ms eficiente que PathGradientBrush. Para el llenado, se utilizan mtodos como : g.FillPolygon(b, points); Para llenar un objeto graphics con un simple color, uno debe de llamar al mtodo Graphics.Clear.

Lesson 2 System.Drawing.Image es una clase abstracta que permite crear, cargar, modificar y grabar imgenes, como BMP, jpg o tif. Al ser sta abstracta, uno debe de crear una instancia usando Image.FromFile, el cual recibe como parmetro un path a la imagen, y Image.FromStream, que recibe un System.IO.Stream como parmetro. O tb uno puede utilizar 2 clases que heredan de Image, como : System.Drawing.Bitmap para imgenes. System.Drawing.Imaging.Metafile para imgenes animadas. Los constructores de Bitmap, te permiten crear un Bitmap a partir de un Image, archivo o stream, o sino crear un bitmap blanco con un height y width especificados. Los 2 mtodos ms importantes que tiene son: GetPixel, el cual devuelve un objeto Color, con los colores de ese pixel. SetPixel, setea el color de un pixel. Por ejemplo, para mostrar una imagen, uno debe de utilizar el sgte cdigo: Image i = Image.FromFile(@"c:...."); pictureBox1.BackgroundImage = i o sino Bitmap b = new Bitmap(@"c:...."); pictureBox1.BackgroundImage = b; Para colocar una imagen como el fondo de un form, se utiliza el sgte cdigo: Bitmap b = new Bitmap("C:...."); Graphics g = this.CreateGraphics(); g.DrawImage(b, 1, 1, this.width, this.height); Para grabar una imagen, el Bitmap usa su mtodo Save

Bitmap.Save, el cual recibe como primer parmetro el nombre del archivo y como 2do, el ImageFormat.Jpeg, segun el formato en que uno desee almacenar la imagen. El JPEG es el ms utilizado para fotos El gif es el ms utilizado para charts. Para obtener el Graphics desde una imagen, se hace lo sgte: Graphics g = Graphics.FromImage(bm); Forma simple de usar Icons Graphics g = this.CreateGraphics(); g.DrawIcon(SystemIcons.Question, 40, 40); o tb se puede usar DrawIconUnstretched Para editar un Icon, se debe de llamar al mtodo Icon.ToBitmap, para de esta forma recin editarlo.

Lesson 3 -- Formatting Text Para adherir texto a una image, se debe de realizar lo sgte: 1. Crear un objeto graphics del image 2. Crear un objeto Font 3. Opcionalmente, crear un objeto Brush 4. Utilizar el mtodo Graphics.DrawString y especificar la ubicacin del texto. Para crear un objeto Font, uno puede usar su constructor: Font f = new Font("Arial", 12, FontStyle.Bold) Donde se pasa como parmetros, el nombre de la fuente, el tamao y un FontStyle Aparte, tb se puede utilizar un objeto FontFamily y pasarlo al constructor. FontFamily ff = new FontFamily("Arial"); Font f = new Font(ff, 12); Adems, uno puede hacer lo sgte: FontConverter converter = new FontConverter(); Font f = (Font) converter.ConvertFromString("Arial, 12pt"); La forma ms simple de pintar un texto en pantalla es: Graphics g = this.CreateGraphics; Font f = new Font("Arial", 40, FontStyle.Bold); g.DrawString("Hola Pitufina", f, Brushes.Blue, 10, 10);

StringFormat te permite configurar el alineamiento y direccion de tu texto. Los miembros ms importantes de StringFormat son: Alignment : StringAlignment.Center centro StringAlignment.Near izquierda StringAlignment.Far derecha FormatFlags: DirectionRightToLeft, texto es mostrado de derecha a izquierda DirectionVertial, es alineado verticalmente DisplayFormatControl FitBlackBox, caracteres que se salen del rectngulo, no son reposicionados LineLimit, permite visualizar todas las lineas. MeasureTrailingSpaces, incluye un espacio al final de cada linea NoClip NoFontFallback, si es que un caracter no es soportado por la fuente que se est colocando, se pone un cuadrado. NoWrap LineAlignment: StringAlignment.Center verticalmente centrado StringAlignment.Near en la parte superior StringAlignment.Far bien abajo Triming, get o set el enumerador String.Trimming, los valores posibles son: Character, el caracter es recortado al caracter ms cercano EllipsisCharacter, el caracter es recortado al caracter ms cercano y una elipse es insertada al final de la linea recortada. EllipsisPath el centro es removido de las recortadas lineas y reemplazadas por una elipse EllipsisWord, especifica que el texto es recortado a la palabra ms cercana y una elipse es insertada la final de la linea recortada None No especifica recorte Word, especifica que el texto es recortado a la palabra ms cercana Para utilizar el dibujar con un StringFormat, se debe de utilizar lo sgte: g.DrawString(cadena, fuente, brush, rectngulo, stringFormat)

Ademas de la clase monitor, se poseen otros mecanismos de sincronizacion: ReadWriterLock Permite lockear acceso a lectores y escritores por separado. Permite multiples lectores para acceder a la data al mismo tiempo, pero solo un escritor puede obtener un lock en la data. Todos los lectores deben liberar su lock antes de que un escritor pueda obtener un lock en la data. Algunas de sus propiedades y metodos importantes son:

- IsReaderLockHeld.- Indica si un lector tiene un lock - IsWriterLockHeld.- Indica si un escritor tiene un lock Para adquirir un lock lector, hacer lo sgte: - Crear una instancia de ReaderWriterLock - Crear un bloque try/catch - Dentro del bloque, adquirir el lock lector llamando a ReaderWriterLock.AcquireReaderLock - Luego de adquirir el lock lector, crear un try/finally para mantener cualquier lectura. - Luego de leer hacer un bloque finally, para liberar el lock, con ReaderWriterLock.ReleaseReaderLock El metodo UpgradeToWriterLock devuelve un LockCookie, es una estructura que el ReaderWriterLock utiliza para permitir el lock escritor a ser bajado (downgraded) cuando se termina de escribir. Los otros objetos kernel que permite sincronizacion son Mutex Semaforo Event Permiten poderosas facilidades de sincronizacion, pero ellos son muy pesados, por ejemplo el Mutex es 33 veces mas lento que la clase Monitor. Pero tal como se menciono, son mas poderosos o potentes, realizan cosas como: - Mutex permite sincronizacion a travs de AppDomain y procesos frontera. - Semaforo es utilizado para dejar acceder a solo un numero de hilos al recurso - Event provee una forma de notificar a multiples hilos que un evento ha ocurrido Todos estos derivan de la clase WaitHandle, que tiene estos metodos o propiedades: - Close, libera todos los recursos utilizados por el actual objeto kernel - WaitOne, bloquea el hilo actual hasta que el objeto kernel es sealado Mutex Trabaja muy parecido al Monitor, solo que tiene esa caracteristica especial que ya se mencion. Para usar Mutex, se siguen los sgtes pasos: 1. Crear una instancia de Mutex para ser compartida a travs de los hilos 2. Crear un if para llamar a WaitOne para esperar a que el lock est disponible 3. Crear un bloque try/finally dentro del bloque if 4. Dentro del bloque try, hacer lo que uno desee teniendo acceso exclusivo 5. Dentro del finally, libera el Mutex, llamando Mutex.ReleaseMutex.

La forma de crear un mutex con un nombre por el cual puede ser llamado luego, es: Mutex mutex = new Mutex(false, "nombre") Y la forma de obtenerlo es Mutext mutex = Mutex.OpenExisting("nombre"); Semaphore Crea un objeto kerenl que soporta un numero de slots validos. Para crear un objeto semaforo, se debe de especificar el numero de slots usados y el maximo de slots: Semaphore semaforo = new Semaphore(0,12); Cuando uno desea liberar slots, se puede hacer indicando la cantidad que se desea liberar semaforo.Release(4); Y tb puede usarse por medio de un nombre, como el mutex semaforo = new Semaphore(0,12,"semaforo"); semaforo = Semaphore.OpenExisting("semaforo"); Event Objeto kernel que posee 2 estados, On y off. Ese estado permite a los hilos esperar hasta que un evento es sealado a hacer algo. Hay 2 tipos de eventos: auto reset y manual reset. Cuando un evento auto reset es sealado, el primer objeto esperando por el evento se vuelve a estado no sealado. Un evento de reseteo manual permite a los hilos esperar por ste para volverse desbloqueados hasta que manualmente resetee el evento a estado no sealado. Estos eventos son clases: AutoResetEvent y ManualResetEvent. Ambas clases heredan de EventWaitHandle. Cuando se crea una de esas clases, se especifica el estado de la seal del evento AutoResetEvent autoEvent = new AutoResetEvent(true); ManualResetEvent manualEvent = new ManualResetEvent(false); La clase EventWaitHandle soporta 2 metodos especificos: Set y Reset, son usados para cambiar de On a Off o viceversa. Asi como en mutex y Semaphore, se puede colocar nombre al evento, de la sgte forma EventWaitHandle evento = new EventWaitHandle(false, EventResetMode.AutoReset, "evento"); evento = EventWaitHandle.OpenExisting("evento");

Lesson 3

Modelo de programacion asncrono. Existen muchos metodos de la forma BeginXXX y EndXXX que permiten trabajar de forma asncrona para as crear otro hilo que trabaje, mientras nosotros realizamos otras cosas en el programa. Por ejemplo, se tiene BeginRead que crea una llamada asncrona y EndRead que espera hasta que la llamada asncrona est completa, por ejemplo: IAsyncResult result = stream.BeginRead(buffer, 0, buffer.Length, null, null); -- Aca va todo lo que queremos hacer mientras se espera int numBytes = stream.EndRead(result); Modelo Rendezvous Existen 3 estilos de programacion asncrona: wait-until-done, polling y callback. Wait-Until-Done Este modelo te permite empezar una llamada asncrona y realizar, por mientras, otras cosas. una vez que se realiz lo que se deseaba, se debe colocar una llamada para bloquearse mientras se espera que la llamada asncrona est completa. Es del estilo de BeginRead y EndRead. Polling Es muy parecido al anterior, solo que la forma de revisar si se ha completado la llamada asncrona, es mediante el objeto IAsyncResult, se consulta a su propiedad IsCompleted, para ver si se termin de realizar o no. Callback El modelo callback requiere que nosotros especifiquemos un mtodo a llamar e incluir cualquier estado que nosotros necesitemos en el metodo callback para completar la llamada. Se realiza de la sgte forma: IAsyncResult result = stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(CompleteRead), stream); El parmetro stream es pork puede ser necesario como el estado de la llamada. En este caso utilizaremos EndRed y cerraremos el stream. static void CompleteRead(IAsyncResult result) { FileStream strm = (FileStream)result.AsyncState; --codigo.... int numBytes = strm.EndRead(result); -- De esta forma podemos llamar a EndRead y este va a retornar sin bloquear strm.Close(); ]

Si es que dentro de la llamada asncrona ocurre una excepcin, sta es mostrada al momento de llamar a EndXXX. Por lo tanto se debe de hacer un try/catch en el momento del EndXXX. ThreadPool .Net te permite usar un pool de hilos que pueden ser usados en muchas situaciones donde necesitas crear tus propios hilos. WaitCallback workItem = new WaitCallback(WorkWithParameter); //es un delegado if (!ThreadPool.QueueUserWorkItem(wokItem, "ThreadPooled")){ Console.WriteLine("No se pudo obtener elemento en cola"); ] La clase ThreadPool da metodos no solo para encolar trabajos, sino ademas administrar el ThreadPool. Sus metodos mas importantes son: GetAvailableThreads, devuelve el numero de hilos disponibles para uso en el pool GetMaxThreads, devuelve el numero maximo de hilos que puede soportar este ThreadPool. GetMinThreads, devuelve el minimo de hilos que son creados en cualquier momento. QueueUserWorkItem, adhiere un trabajo al thread pool, para ser ejecutado en un hilo disponible. Existen 2 situaciones donde se debe de cambiar el limite de hilos del ThreadPool: Inanicin de hilos y aumentar velocidad de hilos. Un completion port, es u hilo de nivel de kernel que es utilizado para hacer operaciones I/O a archivos. Normalmente hay ms completion ports que numeros de hilos administrados. Elevar el numero mnimo de hilos, puede incrementar la performance. Este minimo indica cuantos hilos son creados inmediatamente y seteados en espera para realizar un trabajo. El threadPool puede registrar para espera. Mutex mutex = new Mutex(true); ThreadPool.RegisterWaitForSingleObject(mutex, new WaitOrTimerCallback(MutexHasFired), null, Timeout.Infinite, true); //Seala al mutex causar el hilo a levantar. mutex.ReleaseMutex(); static void MutexHasFired(object state, bool TimedOut) if (timedOut) Console.WriteLine("Mutex timed out"); else Console.WriteLine("Mutex got signaled"); Modelos de hilos son diferentes en Windows Forms que en ASP .NET. La clase SynchronizationContext permite escribir codigo sin importar el modelo de hilos de la aplicacion. Para obtener una instancia, se debe de llamar a SynchronizationContext.Current Luego de esto se pueden realizar diversas cosas:

Llamar a Send, que ejecute un codigo y se va a bloquear hasta que el codigo ejecutado retorne. ctx.Send(RunMe,"Hi"); El metodo Post llama a un codigo y encola el pedido y retorna inmediatamente si es posible. ctx.Post(runMe,"hi"); Timer Cuando se crea el Timer, se especifica un TimerCallback delegado que apunta a un metodo que se desea ejecutar cuando el Times levante. Adems se especifica dentro de cuanto se quiere empezar, as como el tiempo entre firings. Por ejemplo Timer tm = new timer(new TimerCallback(TimerTick), null, 0, 1000); static void TimerTick(object state) Eso va a crear un timer que se ejecute al momento y llame al Callback cada segundo. el metodo Change permite volver a especificar el momento que comienza y los intervalos. tm.Change(0,50);

Capitulo 8
Dominio de aplicacion permite llamar a assemblies externos con la optima eficiencia y seguridad. Servicios son tipos especiales de assemblies que corren en el background, no presentar interfaz de usuario y es controlado por herramientas especiales. Lesson 1 A veces se necesita correr un assembly externo, pero para manejar de mejor forma los riesgos, se crean dominios de aplicacion los cuales llaman a los assemblies con el ambiente protegido. Application Domain es un contenedor lgico que permite correr mltiples assemblies como un solo proceso, previniendo acceder directamente a la memoria de otros assemblies. Ofrece espacios separados de memoria y acceso a recursos. Son ms eficientes que procesos, permitiendo multiples assemblies correr en separados dominios de aplicacin sin la necesidad de correr multiples procesos separados. Un claro ejemplo de Application Domain es el IIS, el cual, si un sitio web es visitado por 10 personas, va crear un application domain por cada uno de ellos. Esencialmente, ASP.NET corre 10 instancias separadas del assembly. Se pueden configurar el behavior de los application domain usando herramientas como Internet Information Services Manager y el .NET Framework Configuration Tool.

Aspnet_wp.exe crea application domains para aislar multiples instancias de un assembly. Uno puede crear su propio application domain para llamar assemblies con el pequeo riesgo de que el assemblie va tomar una accion o acceso a cualquier recurso que no se ha especificado como permitido. Incluso, un Assembly puede almacenar varios Application Domain que almacenen assemblies. Application Domains otorgan confiabilidad y eficiencia: Confiabilidad, usar application domains para aislar tareas que pueden causar que un proceso termine. Si un appDomain se vuelve inestable, se descarga (unload) sin afectar el proceso. Es util cuando se debe correr procesos de largo periodo. Es util tb cuando esa tarea no comparte data. Eficiencia, Si un assembly es cargado en el application domain por default, el assembly no puede ser descargado de memoria mientras el proceso est corriendo. La tcnica de otros application domain minimiza el trabajo de setear procesos de larga duracion que ocasionalmente usan varios DLLs. En .Net para manejar los application domain se posee la clase AppDomain que tiene las sgtes propiedades y metodos: - ActivationContext, obtiene el activation context del actual application domain - ApplicationIdentity, obtiene el identity de la aplicacion en el appDomain. - ApplicationTrust, describe permisos y si una aplicacion es confiable o no. - BaseDirectory, obtiene el directorio base que el resolvedor de assemblies utiliza. - CurrentDomain, obtiene el actual ApplicationDomain del Thread. - DomainManager, obtiene el administrador de dominios que fue provisto por el host cuando el appDomain fue inicializado. - Evidence, obtiene el Evidence asociado al appdomain que es usado para polticas de seguridad. - ApplyPolicy, devuelve el nombre del assembly despues que una politica es aplicada. - CreateComInstanceFrom, crea una instancia de un tipo de COM. - CreateDomain, crea un nuevo appdomain. Para crear una appdomain, se hace lo sgte: AppDomain d = AppDomain.CreateDomain("nombre"); La forma de crear un appdomain y cargar un assembly es de la sgte forma: AppDomain d = AppDomain.CreateDomain("nombre"); d.ExecuteAssembly("assembly.exe");

Una sobrecarga de ese metodo, permite pasar argumentos. Ademas se puede adherir una referencia al assembly y correrlo por nombre usando: d.ExecuteAssemblyByName("assembly"); Cuando necesitamos liberar recursos, debemos descargar los application domain que ya no utilizamos, de la sgte forma: AppDomain.Unload(d);

Lesson 2 Las ms importante configuracin que se tiene que hacer a un appdomain es restringir permisos para reducir riesgos. Defense-in-depth es la seguridad principal de proveer multiples niveles de proteccion, entonces est protegido de una vulnerabilidad. Es muy importante cuando se ejecuta cdigo externo. Evidence es la informacion de un assembly para determinar cual codigo agrupa. Su grupo de codigo determina privilegios del assembly. Comunes formas de evidencia incluyen folders o sitios web que el assembly corre e incluso firmas digitales. Asignando una evidencia a un assembly, hace que se controle los permisos que va a tener.Para esto, se debe de crear un objeto System.Security.Policy.Evidence y pasarlo como parametro al metodo ExecuteAssembly del AppDomain. Cuando se crea un objeto evidencia con el constructor de 2 arreglos de objetos, uno de los arreglos representa los Evidence del host y el segundo, los del assembly. Evidence puede ser cualquier cosa, un string, un integer, una clase customizada, etc. La forma ms simple de controlar permisos asignados a un assembly en un appdomain es pasar evidencia Zone del tipo System.Security.Policy.Zone y el enumerador System.Security.SecurityZone. El sgte codigo demuestra su uso: object[] hostevidence = new Zone(SecurityZone.Internet); Evidence internetEvidence = new Evidence(hosEvidence,null); AppDomain dominio = AppDomain.CreateDomain("dominio"); dominio.ExecuteAssembly("SecondAssembly.exe", internetEvidence); Ademas de esto, se puede proveer de Evidencias de Host a un AppDomain. object[] hostevidence = new Zone(SecurityZone.Internet); Evidence internetEvidence = new Evidence(hosEvidence,null); AppDomain dominio = AppDomain.CreateDomain("dominio", internetEvidence); d.ExecuteAssembly("SecondAssembly.exe");

---Cuando uno crea su AppDomain, la propiedad mas importante es ApplicationBase. Las propiedades del AppDomainSetup son usados por el host para configurar un particular appDomain. Cambiar las propiedades del AppDomainSetup no afectan a ningun AppDomain existente, solo a los que se crean despus. ApplicationBase es la propiedad para setear u obtener el nombre del directorio raiz de la aplicacion. La forma de utilizar esto, es la sgte: AppDomainSetup ads = new AppDomainSetup(); ads.ApplicationBase = "file://" + System.Environment.CurrentDirectory; ads.disallowBindingRedirects = false; ads.DisallowCodeDownload = true; ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; AppDomain d= AppDomain.CreateDomain("nuev dominio", null, ads); Para ver las propiedades del appdomain actual, se hace lo sgte: AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation; Console.WriteLine(ads.ApplicationBase); Console.WriteLine(ads.ApplicationName); Console.WriteLine(ads.DisallowCodeDownload); Console.WriteLine(ads.DisallowBindingRedirects);

Lesson 3 Creando servicios, te permite correr un assembly en background. Los servicios son ideales cuando se necesita monitorear algo, cuando el assembly necesita escuchar por conecciones de red que ingresan, o cuando se necesita ejecutar un assembly antes que el usuario se loguee. Debido a su naturaleza, los servicios requieren seguridad especial y consideraciones de instalacin. Un servicio de window es un proceso que corre en background, sin interfaz de usuario, y en su propia sesin de usuario. Es ideal para una aplicacin que debera estar corriendo constantemente y no interactuar con el usuario. La unica forma de debuggear un servicio es instalandolo, iniciarlo y entonces, atachear un debugger. Uno debe de crear instalador de componentes para el servicio de aplicaciones. Se instalan los componentes y registra el servicio en el servidor y crea una entrada para el servicio con el Windows Services Control Manager. El metodo Main debe cuestionar el comando Run para el servicio que tu proyecto contiene. El mtodo Run carga el servicio en el Services Control Manager.

Windows Service applications corren en una diferente estacin de ventana que la estacin interactiva del usuario no logueado. Una window station es un objeto seguro que contiene un Clipboard, un grupo de objetos de escritorio. Mensajes de error deben ser logueados en el log de eventos de Windows en lugar de levantarlos en la interfaz de usuario. Windows Service application corren en su propio contexto de seguridad y son iniciados antes que el usuario se loguee a Windows. Se debera planear con cuidado qu cuentas de usuario correr con el servicio. Los servicios con mayores privilegios son los que tienen ms ataques. Un service application, contiene 2 links de instaladores, uno para el proceso y otro para el servicio asociado que contiene. Luego de crear el proyecto de servicio, se deben seguir los siguientes pasos: 1. Modificar el ServiceBase.Servicename property. 2. El metodo OnStart se llama cuando se inicializa el servicio, pero no debe quedarse por siempre en ese metodo. Si se desea ejecutar algo, se puede usar el SystemTimers.Timer. 3. Adherir codigo a OnStop method para realizar acciones al momento de parar el servicio. 4. Opcionalmente se pueden sobreescribir OnPause, OnContinue y Onshutdown. Para la instalacin se utilizan ServiceInstaller y ServiceProcessInstaller ServiceInstaller define la descripcion del servicio, su nombre a mostrar, el nombre del servicio y tipo de inicio. ServiceProcessInstaller define los settings del servicio. Los contextos de seguridad pueden ser: LocalService, corre en el contexto de una cuenta que actua sin privilegios de usuario y tiene credenciales de annimo. NetworkService, permite autenticar a otra computadora en la red. LocalSystem, el servicio corre con ilimitados privilegios y presenta credenciales a cualquier usuario remoto. Es de mucho riesgo. User(the default), causa que el sistema pida user name y password cuando el servicio es instalado Capitulo 9 La reversa a una instalacin, no es solo una opcin, sino un mandato. Lesson 1 Configuration Settings Para uno elegir lo mejor, debe de evaluar con exactitud los costos de los beneficios y costos asociados con las desventajas, se tiene que deliverar con calidad del producto y tiempo.

Una de las principales cosas que se deben de evitar es el codigo en duro, ya que el framework te ofrece herramientas para evitar este problema. Hay 2 formas de manejar la configuracin. 1. Setear las propiedades del appSettings, pero es una forma muy rgida. 2. La otra es definir una configuracin customizada y construir las clases correspondientes para administrarlo. El problema ac, es la cantidad de cdigo que se debe de escribir para realizar esto. La facilidad que te otorga el framework es una herramienta para configurar tu aplicacin en pocos minutos sin necesidad de escribir mucho cdigo. El namespace System.Configuration es la librera que sirve como repositorio de todas las clases que los desarrolladores usan para administrar la configuracin. En este namespace se puede encontrar estas 2 clases: Configuration y ConfigurationManager. Sus mtodos y propiedades ms importantes del 1ro son: AppSettings, devuelve el AppSettingsSection que aplica al objeto Configuration. ConnectionStrings, devuelve el objeto ConnectionStrings que aplica al objeto Configuration. FilePath, devuelve el path fsico del archivo de configuracin. GetSection, devuelve el especificado ConfigurationSection. GetSectionGroup, devuelve el especificado ConfigurationSectionGroup. HasFile, indica si el archivo de configuracin existe. Save, este mtodo escribe los settings de configuracin contenidos en el objeto Configuration al xml. SaveAs, lo mismo, solo que se especifica a qu XML. ConfigurationManager ConnectionStrings, devuelve el ConnectionStringsSection GetSection, devuelve una seccin especificada de la configuracin. En s se puede ver que el ConfigurationManager en muchos de sus mtodos, retorna un objeto Configuration como: Configuration cs = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None) ; Configuration cs = ConfigurationManager.OpenMachineConfiguration(); El numerador ConfigurationUserLevel tiene los sgtes valores: None, obtiene el objeto System.Configuration.Configuration que aplica a todos los usuarios.

PerUserRoaming, devuelve el roaming System.Configuration.Configuration que aplica al usuario actual PerUserRoamingAndLocal, devuelve el local System.Configuration.Configuration que aplica al usuario actual. Ademas de esto, se necesita un ExeConfigurationFileMap que sirve para especificar al runtime lo que se quiere hacer y dnde encuentra cada archivo. Cuando uno llama a OpenMappedExeConfiguration o OpenMappedMAchineConfiguration, se esta informando al runtime la intencion de utilizar un mapped file. El unico requisito del constructor es la localizacion de un archivo. Uno tiene que asegurarse que el archivo exista y que se tenga los suficientes permisos para acceder a esta. Common hace refernecia a algunas areas que determinan cmo las aplicaciones se van a ejecutar. Por ejemplo, correr la aplicacin en una versin del framework especificada. Para hacer eso, necesitamos hacer esto: <?xml version ="1.0"> <configuration> <startup> <supportedRuntime version ="v1.1.4322" /> </startup> </configuration> Se tienen ciertas restricciones al respecto: - Si la version del framework en k fue construida la aplicacion, se encuentra en la mquina, se utiliza esta versin. - Si la versin del framework no se encuentra en la mquina y nada fue especificado en supportedRuntime. La aplicacin va a correr en la ltima versin disponible en la mquina. Debera utilizar el framework 2.0 incluso si la aplicacion fue hecha en versiones inferiores. - Si no est la versin del framework, se usa lo que indica el supportedRuntime Para acomodar las tareas de instalar assemblies. 1. Aadir una variable de entorno llamada DEVPATH que apunte a donde se encuentra el assembly 2. Setear el developmentMode a true de esta forma <configuration> <runtime> <developmentMode developerInstallation = "true"/> </runtime> </configuration> Otra tarea importante es indicar donde se encuentra una version especifica del assembly. Para esto se puede usar el .Net Framework 2.0 Configuration Tool. O sino hacerlo de esta forma: <configuration> <runtime> <assemblyBinding xmlns="schemaname">

<dependentAssembly> <assemblyIdentity name ="myprogram" publicKeyToken="xxxxxx" culture="en-us"/> <codeBase version ="x.0.0.0" href="http://www.google.com/milibreria.dll"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration> Otros valores necesarios de configurar son los de AppSettings y ConnectionStrings <configuration> <appSettings> <add key="Mipi" value="patupo"/> </appSettings> <ConnectionStrings> <clear/> <add name="AdventureWorks" providerName="System.Data.SqlClient" connectionString="Data Source=localhost; Initial Catalog=AdventureWorks; Integrated Security=true"/> </ConnectionStrings> </configuration> La forma de utilizar la variable de AppSettings es la sgte: string variable = ConfigurationSettings.AppSettings["mipi"]; Pero la correcta forma de acceder es: NameValueCollection valores = ConfigurationManager.AppSettings; Console.WriteLine(valores["mipi"]); Debido a que ConfigurationSettings es obsoleto. Ademas de esto, cabe resaltar que AppSettings se puede enumerar para iterar sobre este. NameValueCollection valores = ConfigurationManager.AppSettings; int contador = 0; IEnumerator enumerador = valores.Keys.GetEnumerator(); while (enumerador.MoveNext()){ Console.WriteLine (valores.Keys[contador] + " " + valores[contador]); Uno puede usar los connection strings de la sgte forma: ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["Adventure"]; if (settings !=null){ SqlConnection cn = new SqlConnection(settings.ConnectionString); }

En el ambito web se tiene WebConfigurationManager que es muy parecido a ConfigurationManager, pero tiene 3 diferencias: - El WebConfigurationManager tiene el metodo GetWebApplicationSection que la otra clase no tiene, este metodo devuelve una seccion del web.config. Su metodo equivalente es GetSection. - El metodo OpenMappedExeConfiguration del ConfigurationManager es reemplazado por OpenMappedWebConfiguration de la otra clase. - El metodo OpenExeConfiguration del ConfigurationManager es reemplazado por OpenWebconfiguration de la otra clase. La forma de utilizar el WebConfigurationManager es la sgte: ConnectionStringsSection strings = WebConfigurationManager.GetSection("connectionStrings") as ConnectionStringsSection; ConnectionStringSettingsCollection ConnectionStrings = strings.ConnectionStrings; } Application settings Los valores que deberan ir en los valores de configuracin de la aplicacin son: cadenas de conexin, urls de web services, configuraciones remotas, etc. La forma de utilizar los Application Settings, es la siguiente: <applicationSettings> <WindowsApplication2.SampleSettings> <setting name="WebServiceUrl" serializeAs="String"> <value> http://www.adatum.com/myservice.asmx</value> </setting> </WindowsApplication2.SampleSettings> </applicationSettings> Otra forma ms fcil de usar, es crear un nuevo proyecto del tipo Settings File. Este diseador, te permite poder usar el Application Settings de tal forma que no tengas que recordarte tooooodos los valores posibles. Antes se tena que realizar de la sgte forma: [global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("http://www .adatum.com/myservice.asmx")] public string WebServiceUrl{ get{ return ((string)(this["WebServiceUrl"])); } } Y se utiliza de esta forma: SampleSettings settings = new SampleSettings(); Console.WriteLine(settings.WebServiceUrl);

Otra forma de almacenar y devolver valores es ApplicationSettingsBase que posee una coleccin de Key/Value. Lo nico que se necesita para usar esta clase es heredar de ApplicationSettingsBase y decorar cada propiedad que mapee a los valores de configuracin con su UserScopedSettings o ApplicationScopedSettings. class AppSettingsHelper : ApplicationSettingsBase { [UserScopedSetting()] public String key{ get{ return (this["key"] as String);} set{ this["key"] = value;} } [ApplicationScopedSetting()] public String SettingValue{ get{ return (this["SettingValue"] as String);} set{ this["SettingValue"] = value;} } } Uno de los mayores beneficios es la de configuracion de componentes remotos.Es decir, se puede indicar dnde se encuentran ubicados los assemblies sin necesidad de recompilar o deployar nuevamente. La forma de registrar un componente, es la siguiente: <system.runtime.remoting> <application name="MyApplication"> <service> <wellknown type="FullyQualifiedName,AssemblyName" mode="Singleton" objectUri="MyClass.rem"/> </service> </application> </System.runtime.remoting> Para los casos de un IIS, se debe de tener cuidado a la hora de la configuracin, pues se tiene que sealar la mquina donde se encuentra, as como el puerto. <system.runtime.remoting> <application name="MyApplication"> <service> <wellknown type="FullyQualifiedName,AssemblyName" url="http://localhost:5000/MyClass.rem"/> </service> </application> </System.runtime.remoting>

Lesson 2 Creando un instalador El ms importante uso de modificar los settings por default de un dominio de aplicacin es restringir permisos para reducir los riesgos asociados con seguridad. Es decir, cuando es configurado de forma ideal, no solo provee una unidad aislada, sino tambin limita el posible dao que los atacantes puedan hacer si ellos hacen un exploit al assembly. La principal herramienta que nos da el framework .NET para instalar aplicaciones, es la clase Installer. Las principales razones para utilizar installers son: - Otorga una buena apariencia a la aplicacin. - Simplifica lo que tiene que hacer el usuario para usar el producto. - Permiten especificar settings que la aplicacin necesita para correr, permiten generar llaves de registro, generar iconos en el escritorio, y muchas otras caractersticas. - Proveen mecanismos para los usuarios para remover la aplicacin sin dejar rastros en la PC.

La clase Installer es la clase base para crear instaladores customizados. Adems, hay 2 instaladores pre-definidos en el framework, son AssemblyInstaller y ComponentInstaller. Para usar una clase derivada de Installer, se debe de hacer: 1. Heredar de la clase Installer 2. Sobreescribir los mtodos Install, Commit, Rollback y Uninstall 3. Aadir RunInstallerAttribute a la clase y setearlo a true. 4. Colocar la clase derivada en el assembly con tu aplicacin para instalar. 5. Invocar los instaladores. Por ejemplo InstallUtil.exe para invocar los instaladores. La clase Installer tiene una propiedad llamda Installers Qu ocurre cuando se inicia una instalacin? 1. Se llama al mtodo Install. 2. Si ningun error es encontrado el mtodo Commit es llamado al final de la instalacin. (la palabra commit tiene el mismo sentido que en bases de datos) Cosas a tomar en cuenta: - En el proceso o todo es un xito, o todo falla. - Debido a lo anterior, no se va a tener problemas con aplicaciones parcialmente instaladas. - Es necesario un trigger que indique que la instalacin fue un xito, caso contrario, limpiar todo. (Ese mtodo es el Commit) Adems de esto, como contraparte, existe un mtodo llamado Uninstall que permite remover la aplicacin y volver a la mquina a su estado anterior.

Una forma de implementar los 4 metodos luego de hacer la herencia es: public CustomInstaller() : base{ this.Commited += new InstallEventHandler(CustomInstaller_Commited); this.Commmitting += new InstallEventHandler(CustomInstaller_Committing); } private void CustomInstaller_Committing(object sender, InstallEventArgs e){ //Something happen } private void CustonInstaller_Committed(object sender, InstallEventArgs e){ //Committed happened } public override void Install(IDictionary savedState){ base.Install(savedState); } public override void Commit(IDictionary savedState){ base.Commit(savedState); } public override void Rollback(IDictionary savedState){ base.Rollback(savedState); }

Uno puede tener multiples instaladores para hacer multiples cosas. En simples instalaciones va a haber un solo item en la propiedad Installers. Cuando la clase es invocada, cada item en la coleccion es iterada y el correspondiente metodo es llamado: - Si uno tiene exito en la instalacion, el metodo Commit es llamado. - Si hubiera una falla, el metodo Rollback es llamado. - Si la aplicacion esta siendo removida, el metodo Uninstall es llamado. Para ejecutar un instalador de forma programatica, se pueden utilizar las clases AssemblyInstaller o ComponentInstaller. Para esto, es necesario seguir 2 pasos: 1. Crear una instancia del objeto. 2. Llamar al metodo o metodos correspondiente a las acciones que uno quiere realizar con su instalador. Para realizar esto, se debe hacer: IDictionary Actions = new Hashtable(); try{

AssemblyInstaller instaladorAssembly = new AssemblyInstaller("CustomAssembly.exe", args); instaladorAssembly.UseNewContext = true; instaladorAssembly.Install(Actions); instaladorAssembly.Commit(Actions); } catch{ } Para poder realizar el rollback, es decir la desinstalacion, se puede hacer lo mismo pero llamar al Uninstall. IDictionary Actions = new Hashtable(); try{ AssemblyInstaller instaladorAssembly = new AssemblyInstaller("CustomAssembly.exe", args); instaladorAssembly.UseNewContext = true; instaladorAssembly.Uninstall(Actions); } catch{ } Para hacer rollback en vez de desinstalar, se puede hacer instaladorAssembly.Rollback(Actions);

Lesson 3 .Net Framework 2.0 Configuration Tool es una herramienta visual que permite administrar cualquier aspecto referente a la configuracion de un assembly. Esencialmente ayuda a 3 tareas: - Configurar y administrar assemblies localizados en el GAC - Ajustar el codigo para acceder a politicas de seguridad - Ajustar servicios remotos Cuando uno abre esta herramienta, se muestran las sgtes opciones: - Administrar el Cache del Assembly - Ver lista de assemblies en el Assembly Cache - Anhadir un assembly al Assembly Cache - Administrar configuracion de los assemblies - Ver lista de assemblies configurados - Configurar un Assembly - Configurar Politicas de seguridad de acceso del codigo Uno puede configurar sus propias politicas de seguridad entrando a Runtime Security Policy. Dentro de Runtime Security Policy tb se puede incrementar la seguridad que posee un Assembly. Ademas se puede realizar un reseteo de las politicas de seguridad en total. - Ajustar Servicios remotos - Administrar aplicaciones individuales

Para la creacion de nuevos Code Group, se debe de entrar al nodo Code Groups.

Lesson 4 Administracion de Configuracion La forma de obtener una seccion del archivo de configuracion de la aplicacion es: ConfigurationManager.GetSection("seccion") as ValuesHandler; Para grabar los cambios de settings, solo se requiere llamar al metodo Save o SaveAs del objeto Configuration. Si uno no ha seteado la propiedad ForceSave de la propiedad SectionInformation del objeto ConfigurationSection a true, cualquier cambio que se hizo, sera ignorado al momento de hacer Save o SaveAs. Sobre interfaces: La interfaz IConfigurationSectionHandler es usado con propositos de libreria. Otras librerias como ISettingsProviderService y IApplicationSettingsProvider proveen un proposito funcional mas general. El ISettingsProviderService por ejemplo, es usado exclusivamente para soportar el building e tiempo de disenho o sino mejorar los debuggers. Cuando uno necesita un mayor grado de granularidad con las clases, se puede utilizar la interfaz System.Configuration.IConfigurationSectionHandler. Aunque es depreciada en el framework 2.0 y es mejor utilizar ConfigurationSection. Para implementar la interfaz IConfigurationSectionHandler se debe de crear un SectionGroup con la seccion ConfigSection. Los objetos ConfigurationSection son guardados en la propiedad ConfigurationSectionCollection del objeto Configuration. Se debe ver asi: <configSections> <sectionGroup name="seccion" type="DBConnectionStringDemo.MyFirstSectionHandler,DBConnectionStringD emo"/> </configSections> Una forma de recorrer estas secciones es la sgte: Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationLevel.None); ConfigurationSectionGroupCollection grupos = config.SectionGroups; foreach (String nombre in grupos.keys){ Console.WriteLine(nombre); }

Luego de haber creado la seccion, se procede a usar esta seccion de la sgte forma <configSections> <sectionGroup name="seccion" type="DBConnectionStringDemo.MyFirstSectionHandler,DBConnectionStringD emo"/> </configSections> <seccion> <DemoValues> <Value> <Identifier>111</Identifier> <SettingValue>System.Data.SqlClient</SettingValue> </Value> </DemoValues> </seccion> Para usar este tipo de flexibilidad se debe de implementar la interfaz IConfigurationSectionHandler. Solo se debe de implementar su metodo Create. Una forma de hacerlo es la sgte: Hashtable ConfigValues = new Hashtable(); XmlElement Root = section as XmlElement; String TempValue = string.Empty; foreach(XmlNode ParentNode in Root.ChildNodes) { foreach (XmlNode ChildNode in ParentNode.ChildNodes) { if (ChildNode.Name == "Identifier") TempValue = ChildNode.InnerText; if (ChildNode.Name == "SettingValue") ConfigValues[TempValue] = ChildNode.InnerText; } } ValuesHandler handler = new ValuesHandler(ConfigValues); return handler; Y aparte necesitaremos una clase que nos ayude: class ValuesHandler{ private Hashtable customvalue; public ValuesHandler(Hashtable configValues){ this.customvalue = configValues; } public String GetValueFromKey(String key) { return this.customValue[key] as String; }

} El metodo mas importante de este capitulo es ConfigurationManager.GetSection("seccion/DemoValues"); Otra forma mas facil de hacerlo es la sgte: <configSections> <seccion apellido="mipi" nombre="patupo" /> </configSections> Entonces, para obtener los valores, se hace lo sgte: public class ConfigHandler : ConfigurationSection{ [ConfigurationProperty("apellido", IsRequired=false, DefaultValue="No tiene")] public String Apellido{ get{ return (String)base["apellido"];} set{ base["apellido"] = value;} } [ConfigurationProperty("nombre", IsRequired=false, DefaultValue="No tiene")] public String Nombre{ get{ return (String)base["nombre"];} set{ base["nombre"] = value;} } } Y luego usaremos esa clase Configuration conf = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath); ConfigHandler handler = new ConfigHandler; Response.Write(handler.Nombre); Response.Write(handler.Apellido); conf.Sections.Clear(); conf.Sections.Add("Seccion", handler); conf.Save(); Otra interfaz muy util es IApplicationSettingsProvider que tiene 3 metodos: GetPreviousVersion, devuelve el valor de la version previa de la misma aplicacion Reset, resetea los settings de la aplicacion con sus valores por default Upgrade, indica al proveedor que la aplicacion tuvo un upgrade. Los beneficios consecuentes a esta interfaz son: - Ejecucion de diferentes versiones sitio por sitio de una aplicacion - Mantener valores de los settings de una aplicacion cuando esta tiene un upgrade. - Reseteo de los settings a sus valores por defecto.

Hay otros factores que diferencian esta clase de IConfigurationSectionHandler: - Cada propiedad puede ser alcanzada por nivel de aplicacion o usuario. - Valores que son alcanzados a nivel de usuarios son guardados de forma diferente a los alcanzados a nivel de aplicacion. - Si el atributo Application es usado, un archivo de configuracion adicional es creado. Sigue el estandar de convencion de nombre de configuracion, solo que usa el nombre de usuario de la computadora y adhiere .config al final. - Es guardado en Windows Special Folder y puede ser accedido por la clase Application con Application.LocalUserAppDataPath - Acceso es facilitado a traves de LocalFileSettingsProvider La reversa a una instalacin, no es solo una opcin, sino un mandato. Lesson 1 Configuration Settings Para uno elegir lo mejor, debe de evaluar con exactitud los costos de los beneficios y costos asociados con las desventajas, se tiene que deliverar con calidad del producto y tiempo. Una de las principales cosas que se deben de evitar es el codigo en duro, ya que el framework te ofrece herramientas para evitar este problema. Hay 2 formas de manejar la configuracin. 1. Setear las propiedades del appSettings, pero es una forma muy rgida. 2. La otra es definir una configuracin customizada y construir las clases correspondientes para administrarlo. El problema ac, es la cantidad de cdigo que se debe de escribir para realizar esto. La facilidad que te otorga el framework es una herramienta para configurar tu aplicacin en pocos minutos sin necesidad de escribir mucho cdigo. El namespace System.Configuration es la librera que sirve como repositorio de todas las clases que los desarrolladores usan para administrar la configuracin. En este namespace se puede encontrar estas 2 clases: Configuration y ConfigurationManager. Sus mtodos y propiedades ms importantes del 1ro son: AppSettings, devuelve el AppSettingsSection que aplica al objeto Configuration. ConnectionStrings, devuelve el objeto ConnectionStrings que aplica al objeto Configuration. FilePath, devuelve el path fsico del archivo de configuracin. GetSection, devuelve el especificado ConfigurationSection. GetSectionGroup, devuelve el especificado ConfigurationSectionGroup. HasFile, indica si el archivo de configuracin existe.

Save, este mtodo escribe los settings de configuracin contenidos en el objeto Configuration al xml. SaveAs, lo mismo, solo que se especifica a qu XML. ConfigurationManager ConnectionStrings, devuelve el ConnectionStringsSection GetSection, devuelve una seccin especificada de la configuracin. En s se puede ver que el ConfigurationManager en muchos de sus mtodos, retorna un objeto Configuration como: Configuration cs = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None) ; Configuration cs = ConfigurationManager.OpenMachineConfiguration(); El numerador ConfigurationUserLevel tiene los sgtes valores: None, obtiene el objeto System.Configuration.Configuration que aplica a todos los usuarios. PerUserRoaming, devuelve el roaming System.Configuration.Configuration que aplica al usuario actual PerUserRoamingAndLocal, devuelve el local System.Configuration.Configuration que aplica al usuario actual.

Application settings Los valores que deberan ir en los valores de configuracin de la aplicacin son: cadenas de conexin, urls de web services, configuraciones remotas, etc. La forma de utilizar los Application Settings, es la siguiente: <applicationSettings> <WindowsApplication2.SampleSettings> <setting name="WebServiceUrl" serializeAs="String"> <value> http://www.adatum.com/myservice.asmx</value> </setting> </WindowsApplication2.SampleSettings> </applicationSettings> Otra forma ms fcil de usar, es crear un nuevo proyecto del tipo Settings File. Este diseador, te permite poder usar el Application Settings de tal forma que no tengas que recordarte tooooodos los valores posibles. Antes se tena que realizar de la sgte forma: [global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("http://www .adatum.com/myservice.asmx")] public string WebServiceUrl{

get{ return ((string)(this["WebServiceUrl"])); } } Y se utiliza de esta forma: SampleSettings settings = new SampleSettings(); Console.WriteLine(settings.WebServiceUrl); Otra forma de almacenar y devolver valores es ApplicationSettingsBase que posee una coleccin de Key/Value. Lo nico que se necesita para usar esta clase es heredar de ApplicationSettingsBase y decorar cada propiedad que mapee a los valores de configuracin con su UserScopedSettings o ApplicationScopedSettings. class AppSettingsHelper : ApplicationSettingsBase { [UserScopedSetting()] public String key{ get{ return (this["key"] as String);} set{ this["key"] = value;} } [ApplicationScopedSetting()] public String SettingValue{ get{ return (this["SettingValue"] as String);} set{ this["SettingValue"] = value;} } } Uno de los mayores beneficios es la de configuracion de componentes remotos.Es decir, se puede indicar dnde se encuentran ubicados los assemblies sin necesidad de recompilar o deployar nuevamente. La forma de registrar un componente, es la siguiente: <system.runtime.remoting> <application name="MyApplication"> <service> <wellknown type="FullyQualifiedName,AssemblyName" mode="Singleton" objectUri="MyClass.rem"/> </service> </application> </System.runtime.remoting> Para los casos de un IIS, se debe de tener cuidado a la hora de la configuracin, pues se tiene que sealar la mquina donde se encuentra, as como el puerto. <system.runtime.remoting> <application name="MyApplication"> <service> <wellknown type="FullyQualifiedName,AssemblyName"

url="http://localhost:5000/MyClass.rem"/> </service> </application> </System.runtime.remoting>

Lesson 2 Creando un instalador El ms importante uso de modificar los settings por default de un dominio de aplicacin es restringir permisos para reducir los riesgos asociados con seguridad. Es decir, cuando es configurado de forma ideal, no solo provee una unidad aislada, sino tambin limita el posible dao que los atacantes puedan hacer si ellos hacen un exploit al assembly. La principal herramienta que nos da el framework .NET para instalar aplicaciones, es la clase Installer. Las principales razones para utilizar installers son: - Otorga una buena apariencia a la aplicacin. - Simplifica lo que tiene que hacer el usuario para usar el producto. - Permiten especificar settings que la aplicacin necesita para correr, permiten generar llaves de registro, generar iconos en el escritorio, y muchas otras caractersticas. - Proveen mecanismos para los usuarios para remover la aplicacin sin dejar rastros en la PC.

La clase Installer es la clase base para crear instaladores customizados. Adems, hay 2 instaladores pre-definidos en el framework, son AssemblyInstaller y ComponentInstaller. Para usar una clase derivada de Installer, se debe de hacer: 1. Heredar de la clase Installer 2. Sobreescribir los mtodos Install, Commit, Rollback y Uninstall 3. Aadir RunInstallerAttribute a la clase y setearlo a true. 4. Colocar la clase derivada en el assembly con tu aplicacin para instalar. 5. Invocar los instaladores. Por ejemplo InstallUtil.exe para invocar los instaladores. La clase Installer tiene una propiedad llamda Installers Qu ocurre cuando se inicia una instalacin? 1. Se llama al mtodo Install. 2. Si ningun error es encontrado el mtodo Commit es llamado al final de la instalacin. (la palabra commit tiene el mismo sentido que en bases de datos) Cosas a tomar en cuenta: - En el proceso o todo es un xito, o todo falla. - Debido a lo anterior, no se va a tener problemas con aplicaciones parcialmente instaladas.

- Es necesario un trigger que indique que la instalacin fue un xito, caso contrario, limpiar todo. (Ese mtodo es el Commit) Adems de esto, como contraparte, existe un mtodo llamado Uninstall que permite remover la aplicacin y volver a la mquina a su estado anterior. Capiutlo 12 Lesson 1 Autenticacion = identificar al usuario Autorizacion = verificar si el usuario tiene permiso de acceder a algo o no. WindowsIdentity nos da acceso al nombre de usuario actual, tipo de autenticacion y un numero token. Solo almacena el resultado de la autenticacion, incluyendo su username y token. Para crear una instancia de WindowsIdentity se puede llamar a uno de los sgtes 3 metodos: - GetAnonymous, representa un usuario no autenticado - GetCurrent, devuelve el usuario actual de Windows - Impersonate, devuelve un WindowsImpersonationContext que representa un usuario especifico en el sistema. Por ejemplo: WindowsIdentity current = WindowsIdentity.GetCurrent(); Sus propiedades son: - AuthenticationType, cadena que representa el metodo de autenticacion (NTLM normalmente) - IsAnonymous, indica si es anonimo - IsAuthenticated, indica si es usuario autenticado - IsGuest, indica si el usuario es invitado - IsSystem, indica si el usuario es parte del sistema - Name, una cadena representando el dominio y username de la forma "DOMAIN\Username" - Token, un enetero representando el token de autenticacion del usuario La clase WindowsPrincipal da acceso al group membership. Se debe crear usando una instancia de WindowsIdentity. Por ejemplo: WindowsIdentity current = WindowsIdentity.GetCurrent(); WindowsPrincipa principal = new WindowsPrincipal(current); Otra forma de conseguir una instancia, es usando el thread principal AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrin cipal); WindowsPrincipal pricipal = (WindowsPrincipal)Thread.CurrentPrincipal; El metodo mas importante de esta clase es IsInRole, se usa de la sgte forma:

if (principal.IsInRole(WindowsBuiltInRole.Administrator)) .... if (principal.IsInRole(WindowsBuiltInRole.PowerUser)) ... if (principal.IsInRole(WindowsBuiltInRole.User)) .... Tb se puede usar para grupos customizados o grupos en dominio de la base de datos. if (principal.IsInRole(@"CONTOSO\Accounting")) .... Se puede usar System.Environment.MachineName para nombres de grupos de la maquina local. Pero mejor usar System.Environment.UserDomainName para especificar nombres de grupos que existen en maquina local o un Active Directory Domain. La clase PrincipalPermission es util para acciones de seguridad imperativas y declarativas. Se puede combinar cualquiera de las 3 propiedad de esta clase: - Authenticate, indica si requiere que el usuario este autenticado - Name, string indicando el username - Role, string que debe coincidir con uno de los roles principales. El metodo Demand verifica si el usuario activo tiene los permisos indicados. RBS Declarativa Restringe acceso a un metodo completo. El problema que tiene es que si en runtime lanza un excepcion por un evento de windows, entonces windows captura la excepcion y la aplicacion se puede detener. Para usar RBS declarativa, se debe tener 3 elementos en el codigo: - El metodo System.AppDomain.CurrentDomain.SetPrincipalPolicy para especificar la politica de seguridad. - Bloque try/catch para capturar acceso desprivilegiado y reportarlo como error. - Atributo PrincipalPermission para declarar requerimientos de acceso a metodo. Por ejemplo, para llamar a un metodo protegido con esa seguridad se hace lo sgte: try {AdministratorOnyMethod();} catch(System.Security.SecurityException ex) {Console.WriteLine(ex);} Se pueden declarar mas de una declarativa de demanda de la sgte forma:

[PrincipalPermission(SecurityAction.Demand, Name= @"CONTOSO\Administrator")] [PrincipalPermission(SecurityAction.Demand, Name= @"CONTOSO\User1", Role=@"CONTOSO\Managers")] [PrincipalPermission(SecurityAction.Demand, Authenticated = true)] static void AdministratorsOnlyMethod() {...} RBS imperativa Permite restringir el acceso a porciones de metodos. Para usarlo se deben de tener 4 elementos: - El metodo System.AppDomain.CurrentDomain.SetPrincipalPolicy para especificar las politicas de seguridad. - Bloque Try/catch para capturar accesos no privilegiados. - Objeto PrincipalPermission con propiedades acordes a las restricciones que se desean imponer. - Llamada al metodo PrincipalPermission.Demand para declarar los requerimientos de acceso al metodo. PrincipalPermission tiene 3 constructores: - PrincipalPermission(PermissionState) - PrincipalPermission(Name, Role), especifica solo nombre y rol, si se quiere especificar solo uno, el otro se pone null. - PrincipalPermission(Name, Role, Authenticated) Por ejemplo, el sgte codigo lanza excepcion si el usuario no es miembro del grupo Administrators: PrincipalPermission p = new PrincipalPermission(null, @"BUILTIN\Administrators", true); p.Demand(); Si es que manda excepcion, se captura como System.Security.SecurityException La interfaz IIdentity sirve para crear custom identity classes. Clases como WindowsIdentity, FormsIdentity y PassportIdentity implementan esta interfaz. Mientras que GenericIdentity ofrece una implementacion flexible de IIdentity. Para implementar esta interfaz, se deben implementar las sgtes propiedades: - AuthenticationType, string donde se almacena descripcion del mecanismo de autenticacion del usuario. - IsAuthenticated, se setea este valor en true cuando el usuario ha sido autenticado. - Name, string que guarda el username. Adicional a esto, se debe implementar un constructor que defina cada una de las propiedades. Por ejemplo: class CustomIdentity : IIdentity

{ private bool isAuthenticated; private string name, authenticationType; private string firstName, lastName, address, city, state, zip; public CustomIdentitu(){ //Se setea a null, false o "None" } //En el constructor con parametros, se setea todo y a la variable name se le asigna nombre y apellido } WindowsPrincipal y GenericPrincipal estan basados en la interfaz IPrincipal. Los objetos basados en esta interfaz representan el contexto de seguridad de un usuario, incluyendo la identidad del usuario y cualquier rol o grupo al que pertenezca. Para implementar la interfaz IPrincipal, por lo menos se debe de implementar un constructor, una propiedad y un metodo. El constructor debe aceptar un objeto IIdentity y un arreglo de strings que contienen los roles de identidad. La propiedad que se debe implementar es IPrincipal.Identity que debe devolver el identity principal del objeto. El metodo IPrincipal.IsInRole que toma un string y un rol y retorna true cuando el identity principal es un miembro de ese rol; sino retorna false. Se puede aadir otras funcionalidades sobreescribiendo IPrincipal: - Aadir una propiedad Roles que devuelva un arreglo de strings conteniendo los roles del usuario - Metodos IsInAllRoles y IsInAnyRole que indiquen si el usuario es miembro de multiples roles - Metodos IsHigherThanRole y IsLowerThanRole que habiliten jerarquia en grupos de membresia. La forma de implementar es la sgte: class CustomPrincipal : IPrincipal { private IIdentity identity; private string[] roles; public CustomPrincipal(IIdentity identity, string[] roles) {//setear } public IIdentity Identity { get {return identity;}} public bool IsInRole(string role) { return Array.BinarySearch(roles, role)>0? true : false;} }

Como crear simples modelos de privilegio de usuario customizados: Si solo se necesita la funcionalidad basica que ofrecen IIdentity y IPrincipal, se deberia usar System.Security.Principal.GenericIdentity y System.Security.Principal.GenericPrincipal. Estas clases implementan solo las propiedades y metodos requeridos por las interfaces. Cada uno ofrece constructores que tu aplicacion debe de usar para especificar las propiedades de la clase. GenericIdentity o usar username GenericIdentity GenericIdentity tiene 2 constructores. Se puede usar solo un username, y tipo de autenticacion. user1 = new GenericIdentity("Anakin"); user2 = new GenericIdentity("Anakin","SmartCard");

GenericPrincipal tiene u solo constructor que requiere un GenericIdentity y un arreglo de string que contiene los roles de identidad. String[] roles = new String[]{"Users","Administrator"}; GenericPrincipal principal = new GenericPrincipal(user1, roles); principal.IsInRole("users") deberia retornar true.

Si es que se define custom IIdentity y IPrincipal, o se usa GenericIdentity y GenericPrincipal, se puede usar declarativa e imperativa RBS siguiendo los pasos: 1. Crear un objeto IIdentity o GenericIdentity que represente al usuario actual. 2. Crear un objeto IPrincipal o GenericPrincipal basado en mi objeto IIdentity 3. Setear Thread.CurrentPrincipal a mi objeto IPrincipal 4. Adherir una declarativa o imperativa RBS. Para manejar autenticaciones remotas, se usa: System.Net.Security.NegotiateStream o System.Net.Security.SslStream. Las excepciones que se manejan si hay error en autenticacion remota son: System.Security.Authentication.AuthenticationException System.Security.Authentication.InvalidCredentialException Lesson 2 Usando listas de control de acceso ACL = Access Control Lists ACLs son la tecnica mas commun para restringir acceso a archivos, carpetas, servicios, etc. Discretionary Access Control List = DACL Es un mecanismo de restriccion de autorizacion que identifica los usuarios y grupos que son permitidos o denegados de acceder a un objeto.

DACL es contorlado por el duenho del objeto o la persona que creo el objeto, este contiene ACEs (access control entries) que determinar acceso del usuario al objeto. Un Ace es una entrada en un DACL. Para administrar los permisos de forma mas eficiente, Windows incluye el concepto de herencia. Se puede administrar permisos de forma declarativa, asignando un DACL a cada objeto o se usa la herencia, la cual es mas eficiente. ACEs pueden asignar directamente derechos al usuario o a un grupo. Adicionalmete, usuarios pueden ser miembros de multiples grupos. Entonces, un usuario puede tener diferentes ACEs en un solo ACL. Los permisos otorgados a un ususario o grupo son acumulativos. Por ejemplo Lucia pertence a 2 grupos: Inventario y Manager. El ACL tiene a Lucia con derechos de lectura, el grupo de inventario con derechos de modificar y el grupo de Managers con Full Control. Entonces Lucia va a tener derechos Full Control. ACEs que niegan acceso, siempre sobreescriben ACEs que otorgan acceso. Por ejemplo, si hay un ACE de Inventario que niegue acceso a un archivo, entonces Lucia no puede abrir ese archivo, a pesar de que al pertenecer al grupo Managers tenga Full Control. Permisos para diferentes recursos funcionan similarmente y todas las clases heredan de una clase base comun. FileSystemRight es un enumerador para especificar permisos a archivos y directorios. Tiene 24 miembros, mencionaremos algunos: - FullControl, tiene acceso total a un archivo o carpeta. - Modify, usuarios pueden leer, editar y eliminar archivos o carpetas - RedAndExecute, usuarios pueden ver archivos y ejecutar aplicaciones. - ListDirectory, usuarios pueden explorar una carpeta - Read, usuarios pueden ver archivos o el contenido de una carpeta. - Write, usuarios pueden crear archivos en un directorio, pero ellos no pueden leerlos. - Other members, Permisos especiales son mas granulares permisos que el estandar que uno desea trabajar. Security Access Control List = SACL Es mecanismo de log de eventos que determina como el acceso a una fila o carpeta es auditado. Un SACL no puede restringir el acceso a un achivo o carpeta. SACL puede causar un evento a ser guardado en el log de eventos de seguridad cuando un usuario accede a un archivo o carpeta. Es muy util para auditar y es ua herramienta critica en deteccion de intrusos. SACLs determina las condiciones bajo las cuales el acceso a un objeto es auditado. Un desarrollador usa SACLs para trackear recursos que su aplicacion esta negada de acceso, para entonces poder customizar la aplicacion para permitirla correr sin problemas bajo una cuenta de privilegios menor. Para habilitar el logueo de eventos, se debe habilitar el Audit Object Access de la computadora.

System.Security.AccessControl contiene muchas clases para ver y configurar ACLs de diferentes tipos de objetos. Se usan las clases de este namespace para acceder a DACLs, SACLs y ACEs para archivos, carpetas, llaves de registro, llaves de criptografia, manejadores de eventos de espera, mutexes y semaforos. Se tienen 3 clases ACL: - <Type>Security, es la clase mas comun usada, tiene metodos para devolver coleccion de DACLs o SACLs y anhadir o remover ACLs. Todas las clases heredan de NativeObjectSecurity - <Type>AccessRule, representa un set de permitir o negar derechos de acceso a un usuario o grupo. Las clases heredan de AccessRule, la cual hereda de AuthorizationRule. - <Type>AuditRule, representa u set de permisos de acceso a ser auditados para un usuario o grupo. Hereda de AuditRule, la cual hereda de AuthorizationRule. Para analizar un ACL se deben de seguir los sgtes pasos: 1. Crear una instancia que herede de NativeObjectSecurity, como DirectorySecurity, FileSecurity, RegistrySecurity o MutexSecurity 2. Llamar al metodo GetAccessRules para devolver una instancia de AuthorizationRuleCollection 3. Iterar a traves de los items para devolver y analizar un ACL individual. Ejemplo: DirectorySecurity ds = new DirectorySecurity(@"C:\Program Files", AccessControlSections.Access); AuthorizationRuleCollection arc = ds.GetAccessRules(true, true, typeof(NTAccount)); foreach(FileSystemAccessRule ar in arc) Console.WriteLine(ar.IdentifyReference + ar.AccessControlType + ar.FileSystemRights); Para analizar SACLs, se deben seguir los mismos pasos, pero llamar a GetAuditRules en lugar de GetAccessRules y sustituir clases audit. Para configurar ACLs se deben seguir los sgtes pasos: 1. Llamar al metodo GetAccessControl para obtener una instancia de una clase que herede de NativeObjectSecurity, tales como DirectorySecurity, FileSecurity, etc. 2. Adherir o remover entradas ACL de un objeto. 3. Llamar al metodo SetAccessControl para aplicar los cambios. ejemplo: string dir = @"C:\Test"; DirectorySecurity ds = Directory.GetAccessControl(dir); ds.AddAccessRule(new FilesystemAccessRule("Guest", FileSystemRights.Read, AccessControlType.Allow)); Directory.SetAccessControl(dir, ds);

Lesson 3: Encriptando y Desencriptando data Encriptando y Desencriptando con llaves simetricas Llave simetrica es cuando el que envia y el que recibe conocen la forma de encriptar y desencriptar, pues es la misma. Symmetric key encryption es una tecnica de encriptar que usas una sola llave secreta para encriptar y desencriptar. Esta encriptacion es rapida y util para encriptar larga cantidad de datos. Desventaja, se asume que el enviante receptor tienen la llave. Clases de Symmetric Algorithm Algunas clases en .Net son: - RijndaelManaged, es la unica clase que es completamente administrada. - RC2, estandar de encriptar disenhado para reemplazar a DES que usa tamanho de las llaves. - DES, Data Encryption Standar, usa llaves de corto tamanho - TripleDES, aplica el algoritmo DES 3 veces. Todas estas clases heredan de System.Security.Cryptography.SymmetricAlgorithm y compartes las sgtes propiedades: - BlockSize, propiedad del tamanho de la operacion de criptografia en bits. - FeedbackSize, propiedad del tamaho del comentario de la operacion de criptografia en bits. - IV, obtiene o setea el vector de iniciacion para el algoritmo simetrico. - Key, devuelve o setea la llave secreta para el algoritmo simetrico. - KeySize, devuelve o setea el tamanho de la llave secreta usada por el algoritmo simetrico, en bits. - Mode, setea uno de los valores del enumerador CipherMode que determina un aspecto del algoritmo de encriptacion. Es usualmente seteado a CipherBlockChaining. - Padding, valores del enumerador PaddingMode, determina como el algoritmo de encriptacin llena cualquier diferencia entre el bloque del algoritmo y el tamanho del texto plano. Normalmente no se cambia. Adicionalmente tiene los sgtes metodos: - CreateEncryptor, crea un objeto encriptador simetrico usado por CryptoStream para encriptar un stream. - GenerateIV, genera un random IV - GenerateKey, genera una llave random a ser usada en el algoritmo. - ValidKeySize, determina si el tamanho de la llave es valida para el algoritmo actual y retorna un valor booleano. Si es que se desea usar un password como llave, lo mejor seria usar la clase System.Security.Cryptography.Rfc2898DeriveBytes para cambiar un password a una llave. Este metodo recibe como parametros: el password, el salt value y el numero de iteraciones utilizadas para generar la llave. Luego de haber pasado esos 3 parametros al constructor, se puede obtener la llave llamando al metodo Rfc2898DeriveBytes.GetBytes. Este

metodo aceptar el numero de bytes a retornar. Tener cuidado porque el algoritmo tiene KeySize y BlockSize en bits. El tamanho del IV debe ser basado en la propiedad BlockSize. ejemplo: string password = "P@S5w0rd"; RijndaelManaged algoritmo = new RijndaelManaged(); byte[] salt = Encoding.ASCII.GetBytes("this is my salt"); Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt); algoritmo.Key = key.GetBytes(algoritmo.KeySize/8); algoritmo.IV = key.GetBytes(algoritmo.BlockSize/8); Para encriptar y desencriptar mensajes en la aplicacion, se debe hacer lo sgte: 1. Crea un objeto Stream como interfaz con la memoria o un archivo que va a ser leido o escrito. 2. Crea un objeto SymmetricAlgorithm 3. Especificar la llave de algoritmo y el IV 4. Llamar a SymmetricAlgorithm.CreateEncryptor() o SymmetricAlgorithm.CreateDecryptor para crear un objeto ICryptoTransform 5. Crea un objeto CryptoStream usando el objeto Stream y el objeto ICryptoTransform 6. Leer o escribir desde el objeto CryptoStream. ejemplo: string inFileName = @"C:\Boot.ini"; string outFileName = @"C:\Boot.ini.enc"; //Paso 1 FileStream inFile = new FileStream(inFileName, FileMode.Open, FileAccess.Read); FileStream outFile = new FileStream(outFileName, FileMode.OpenOrCreate, FileAccess.Write); //Creamos el objeto algoritmo SymmetricAlgorithm algo = new RijndaelManager(); //Especificamos la llave algo.GenerateKey(); //Leelmos el archivo desencriptado byte[] fileData = new byte[inFile.Length]; inFile.Read(fileData, 0 , (int)inFile.Length); //Creamos el ICryptoTransform ICryptoTransform encryptor = algo.CreateEncryptor(); //Creamos el CryptoStream CryptoStream encryptStream = new CryptoStream(outFile, encryptor, CryptoStreamMode.Write); encryptStream.Write(fileData,0,fileData.Length); encryptStream.Close();

inFile.Close(); outFile.Close(); Para desencriptar, se debe de leer la llave y el IV usados para encriptar. usar el CreateDecryptor en vez de CreateEncryptor Cambiar el CryptoStreamMode.Write a CryptoStreamMode.Read. Encriptacion y desencriptacion con llave asimetrica Encriptacion asimetrica es conocida como encriptacion de llave publica. Mensajes encriptados con la llave publica pueden ser desencriptados solo con la llave privada, lo cual permite a cualquiera enviar un mensaje encriptado que puede ser desencriptado solo por una persona. Algoritmos asimetricos no son mas rapidos que los simetricos, pero son mas dificiles de romper. No son muy usados para encriptar grandes cantidad de datos debido a su performance. Un uso comun de este algoritmo es encriptar y transferir una llave simetrica y un IV. Encriptacion asimetrica es usada solo durante el establecimiento de sesion de HTTPS y SSL. Para la administracion de llaves en encriptacion asimetrica, se usa un PKI (public key infrastructure), tales como Certificate Services incluidos con Windows Server 2003. PKI sirve para distribuir, administrar y revocar certificados en una organizacion. Clases de algoritmo asimetrico en .Net La clase base system.Security.Cryptography.AsymmetricAlgorithm tiene las sgtes propiedades: - KeyExchangeAlgorithm, devuelve el nombre del algoritmo de intercambio de llaves. - KeySize, devuelve o setea el tamanho de la llave secreta usada por el algoritmo simetrico, en bits. - LegalKeysizes, es un arreglo de KeySizes que devuelve los tamanhos de llave que son soportados por algoritmo simetrico. Cada miembro del arreglo contiene un MinSize y un MaxSize. - SignatureAlgorithm, devuelve el URL de un documento XML describiendo la firma del algoritmo. La clase AsymmetricAlgorithm no tiene metodos utiles. Existen 2 implementaciones de esta clase: - RSACryptoServiceProvider, usada para todas las encriptaciones y desencriptaciones asimetricas. Implementa el algoritmo RSA - DSACryptoServiceProvider, usada para mensajes con firma digital. RSACryptoServiceProvider provee las sgtes propiedades: - PersistKeyInCsp, devuelve o setea un valor indicando si la llave deberia persistir en el CSP. Setear a true cuando se desea reusar la llave. - UseMachineKeyStore, devuelve o setea un valor indicando si la llave deberia ser persistida en el almacenamiento de llave de la computadora del user profile.

CSP = proveedor de servicios criptograficos Aparte tiene los metodos: - Decrypt, desencripta datos con el algoritmo RSA - Encrypt, encripta datos con el algoritmo RSA - ExportParameters, exporta una estructura RSAParameters, la cual define el par llave de algoritmo. Pasar true al metodo para exportar ambos, el privado y publica llave, o false para exportar solo la publica. - FromXmlString, importa un key pair desde una cadena XML. - ImportParameters, importa a una llave publica o key pair el especificado RSAParameters - SignData, computa el valor hash y guarda la firma en un arreglo de bytes - SignHash, computa la firma de un hash especificado, encriptandolo con la llave privada y guardando la firma en un arreglo de bytes - VerifyData, verifica la especificada firma de datos comparandolo con la firma computada por los datos. - VerifyHash, verifica la especificada firma de datos comparandolo con la firma computada por los valores hash. Como exportar e importar llaves asimetricas y key pairs. Llaves RSA son mucho mas complejas que llaves de encriptacion simetrica. Llaves RSA son llamadas parametros y son representadas por una estructura RSAParameters. La estructura es la sgte: - D, llave privada - Exponent, tb conocida como e, esta es la parte pequenha de la llave publica - Modulus, conocida como n, esta es la parte larga de la llave publica. Sin la llave publica nadie puede encriptar mensajes para ti. Para exportar tu llave publica a una instancia de la estructura RSAParameters, se usa el metodo RSACryptoServiceProvider.ExportParameters y se pasa un booleano false como parametro. El parametro false causa que el metodo exporte solo la llave publica. Si fuera true, ExportParameters exportaria la llave publica y la llave privada. Ejemplo: RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); RSAParameters publickey = rsa.ExportParameters(false); Para guardar o transmitir la llave exportada, se deberia usar RSACryptoServiceProvider.ToXmlString. Recibe un parametro booleando que indica si la llave privada deberia ser exportada. Como guardar Key Pairs para usarlos despues? Se pude exportar llaves al CSP usando CryptoAPI. Para guardar llaves privadas de forma persistente, anhadir los siguientes elementos al codigo 1. Crear un objeto CspParameters 2. Especificar la propiedad CspParameters.KeyContainerName

3. Crear un objeto RSACryptoServiceProvider usando el constructor sobrecargado que acepta un objeto CspParameters 4. Setea a true la propiedad RSACryptoServiceProvider.PersisKeyInCsp ejemplo: CspParameters persistantCsp = new CspParameters(); persistantCsp.KeycontainerName = "ejemplo"; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(persistantCsp); rsa.PersistKeyInCsp = true; RSAParameters privateKey = rsa.ExportParameters(true); foreach(byte thisByte in privateKey.D) Console.WriteLine(thisByte.ToString("X2"));

Como encriptar y desencriptar mensajes usando encriptacion asimetrica Para realizar esta tarea se llama a los metodos RSACryptoServiceProvider.Encrypt y RSACryptoServiceProvider.Decrypt. Ambos toman los parametros: - byte[] rgb, un arreglo de bytes conteniendo el mensaje a ser encriptado o desencriptado - bool fOAEP, booleando. Si es true, encriptacion y desencriptacion va usar OAEP data padding (solo para XP). Si es false PKCS#1 v1.5 data padding. ejemplo: string message = "Hello World"; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); byte[] messageBytes = Encoding.Unicode.GetBytes(message); byte[] encriptado = rsa.Encrypt(messageBytes, false); byte[] desencriptado = rsa.Decrypt(encriptado, false); Console.WriteLine(Encoding.Unicode.GetString(desencriptado));

Validando integridad de datos con Hashes Se puede usar el valor del hash para verificar si un archivo no ha sido modificada luego de haber sido generada. Crear un hash es una operacion en un solo sentido. Hashes son a veces usados para permitir a los passwords ser verificados sin guardar el password en si. Algoritmos Hash en .Net Framework Se tienen los sgtes algoritmos: MD5, RIPEMD160, SHA1, SHA256, SHA384, SHA512

Keyed hash algoritmos, protegen la modificacion del hash, encriptandolo usando una llave secreta que el enviador y receptor deben tener. Las clases de algoritmos keyed hash son: - HMACSHA1, hash basado en SHA1. - MACTripleDES, usa TripleDES. Como computar un Nonkeyed hash Se siguen los sgtes pasos: 1. Crear un objeto de algoritmo hash 2. Guardar la data a ser hasheada en un arreglo de bytes 3. Llamar al metodo HashAlgorithm.ComputeHash 4. Recuperar el arreglo de bytes HashAlgorithm.Hash, el cual contiene el valor hash. Ejemplo> MD5 hash = new MD5CryptoServiceProvider(); FileStream file = new FileStream("archivo.txt", FileMode.Open, FileAccess.Read); Binaryreader reader = new BinaryReader(file); hash.ComputeHash(reader.ReadBytes((int)file.Length)); Console.WriteLine(Convert.ToBase64String(hash.Hash));

Como computar un Keyed Hash Se deben seguir los sgtes pasos: 1. Crear una llave secreta que es compartida por todos los participantes quienes van a computar o verificar el hash 2. Crear un objeto algoritmo hash usando la llave secreta, si no se provee una llave, esta va a ser generada automaticamente. 3. Guardar la data a ser hasheada en un arreglo de bytes. 4. Llamar al metodo KeyedHashAlgorithm.ComputeHash. 5. Devolver el arreglo de bytes KeyedHashAlgorithm.Hash, el cual contiene el valor hash ejemplo: byte[] saltValueBytes = Encoding.ASCII.GetBytes("This is my salt"); Rfc2898DeriveBytes passwordKey = new Rfc2898DeriveBytes("password", saltValueBytes); byte[] secretKey = passwordKey.GetBytes(16); //Creando objeto algoritmo hash HMACSHA1 hash = new HMACSHA1(secretkey); FileStream file = new FileStream("archivo.txt", FileMode.Open, FileAccess.Read); BinaryReader reader = new BinaryReader(file); has.ComputeHash(reader.ReadBytes((int)file.Length));

Console.WriteLine(Convert.ToBase64String(hash.Hash)); Este tipo de metodos, previenen un ataque de modificacion de hash. Estan usando un password que va a utilizar el hash. Signing Files (firmando archivos) Una firma digital es un valor que puede ser agregado a data electronica para informar que este fue creado por alguien que posee una llave privada especifica. Public/key algorithm puede ser usado para formularios de firmas digitales. Clases de .Net Framework para firmas digitales Se poseen 2 clases para generar y verificar firmas digitales: DSACryptoServiceProvider y RSACryptoServiceProvider. Estas clases usan diferentes algoritmos, pero ofrecen funcionalidad similar. Cada uno implementa los siguientes 4 metodos para usar con firmas digitales: - SignHash, genera una firma digital basada en el hash de un archivo. - SignData, genera una firma digital, primero genera un hash de un archivo y luego genera una firma basada en el hash. - VerifyHash, Verifica una firma digital basada en el hash de un archivo - VerifyData, verifica una firma digital dando el contenido de un archivo. Firmas Digitales proveen metodos de generar y verificar, a diferencia de los algoritmos hash. Las firmas digitales usan encriptacion asimetrica. Por lo cual el receptor no puede regenerar la firma sin la llave privada del enviador. Pero, la firma puede ser verificada usando la llave publica del que envia. Para generar una firma digital desde un archivo, se deben realizar los sgtes pasos: 1. Crear un objeto algoritmo de firma digital 2. Guardar la data que sera firmada, en un arreglo de bytes 3. Llamar a SignData y guardar la firma 4. Exportar la llave publica Para verificar la firma digital, seguir los sgtes pasos: 1. Crear un objeto algoritmo de firma digital 2. Importar la firma y la llave publica. 3. Guardar la data a ser verificada, en un arreglo de bytes 4. Llamar al metodo verifyData ejemplo: DSACryptoServiceProvider signer = new DSACryptoServiceProvider(); FileStream file = new FileStream("archivo.txt", FileMode.Open, FileAccess.Read); BinaryReader reader = new BinaryReader(file); byte[] data = reader.ReadBytes((int)file.Length);

//Guardamos la firma byte[] signature = signer.SignData(data); //Exportamos la llave publica string publickey = signer.ToXmlString(false); Console.WriteLine(Convert.ToBase64String(signature)); //Verificacion DSACryptoServiceProvider verifier = new DSACryptoServiceProvider(); //Importamos la firma y la llave publica verifier.FromXmlString(publickey); //Guardamos la data a ser verificada en un arreglo de bytes FileStream file2 = new FileStream("archivo.txt", FileMode.Open, FileAccess.Read); BinaryReader reader2 = new BinaryReader(file2); byte[] data2 = reader2.ReadBytes((int)file2.Length); //Llamando al metodo para verificar la data if (Verifier.VerifyData(data2,signature)) Console.WriteLine("Firma verificada"); else Console.WriteLine("Firma verificada"); reader2.Close(); file2.Close(); Capitulo 13 Interoperation Interoperation es el nombre generico usado para referirse al proceso de interactuar con codigo no administrado, desde un codigo administrado. Por ejemplo. Una aplicacion puede necesitar tomar control de Excel y hacer una rutina. Debido a que el Excel no esta escrito en .Net, se necesita acceder a traves de un COM (Component Object Mode). COM y .NET son 2 diferentes ambientes de ejecucion, entonces deben compartir librerias entre ellos para usar interoperation, la cual es conocida como Interop. Lesson 1 Usando objetos COM Importing Type libraries El framework provee soporte de interoperabilidad para COM y la habilidad de importar type libraries tb. El mecanismo para comunicar .Net con componentes COM es conocido como Runtime Callable Wrapper (RCW), este maneja la mayoria de trabajo, como los tipos, manejo de evento y manejo de interfaces. Los componentes COM deben ser registrados antes de ser utilizados. Luego de ser registrados, necesitan ser importados usando Visual Studio 2005 o la Type Library Importer tool (tlblmp.exe).

Asumamos que tenemos un dll llamado Person.dll que contiene la sgte estructura: VB6 Private mFirstName As String Private mLastName As String Property Get FirstName() As String mFirstName = FirstName End Property Property Let FirstName(Value As String) mFirstName = Value End Property Ejecuta el comando Regsvr32 para asegurar que Person.dll esta registrado: Regsvr32 Person.dll, ahora con eso el dll ha sido registrado y necesita importarse. Se puede hacer con Visual Studio 2005 o tlbImp.exe Para adherirlo con Visual studio 2005, solo se da click derecho al proyecto, add reference e ir al tab de COM y seleccionar el que deseamos. Para hacer con el tlbimp, se hace tlbimp nombreDLL.dll y eso genera un nuevo assembly de .NET el cual se anhade a cualquier proyecto, como cualquier assembly. Algunos problemas que se generan con c# es que los componentes COM no soportan sobrecarga de parametros, entonces por cada valor en la lista de parametros se debe pasar algo. Incluso, no se puede pasar un valor null. Esto puede causar problemas de codigo innecesario y muchas instancias hacen que el codigo no sea muy legible. Para direccionar ese problema, una nueva caracteristica de la clase Type se ha anhadido: Type.Missing. Ejem que no compila por la ultima linea: using Microsoft.Office.Core; using Microsoft.Office.Interop.Excel; Application NewExcelApp = new Application(); //Esto no va a compilar NewExcelApp.Worksheets.Add(); Usando Type.Missing class Program { private static Object opcional = Type.Missing; static void Main(string[] args) { Application excel = new Application();

excel.Worksheets.Add(ref opcional, ref opcional, ref opcional, ref opcional); } } Herramientas usadas por COM Interop El framework y VS2005 proveen multiples herramientas que son usadas por COM Interop. Son explicados: - Type Library Importer, tlbImp.exe - Type Library Exporter, tlbExp.exe, crea una libreria del tipo COM que puede ser consumida por una aplicacion .NET - Registry Editor, Regedit.exe, Todos los componentes COM deben tener un entry en el registro de Windows. - Intermediate Language Disassembler, Ildasm.exe, permite ver una representacion visual del lenguaje intermedio (IL = Intermediate Language) - Assembly Registrarion Tool, Regasm.exe, permite anhadir assemblies .NET y removerlos desde la base de datos Usando objetos COM en codigo: Por ejemplo, abriremos un documento pdf con la libreria de Acrobat Reader: axAcroPDF1.LoadFile(@"documento.pdf"); axAcroPDF1.Print();

Manejando Excepciones en COM interop Para el manejo de excepciones, se utiliza el RuntimeWrappedException, pues el lenguaje COM no esta dentro del CLS. Propiedades: - Data, coleccion key/value que provee informacion adicional de la excepcion. - HelpLink, get o sets un link al archivo de ayuda asociado con la excepcion - InnerException, get la instancia de la excepcion causada por la excepcion actual - Message, mensaje que describe la excepcion - Source, get or sets el nombre de la aplicacion u objeto que causo el error. - StackTrace, devuelve un string que representa de los frames en la llamada al stack en el momento que la excepcion fue lanzada. - TargetSite, devuelve el metodo que lanzo el error - WrappedException, devuelve el objeto que envuelto por el RuntimeWrappedException Actualmente Exception captura ese tipo de excepciones. ejemplo: using System.Runtime.CompilerServices; [assembly: RuntimeCompatibility(WrapNonExceptionThrows=false)] Limitaciones de COM interop

- statics/shared members, no permite soporte de miembros estaticos y compartidos. - Parameterized constructors, tipos COM no permiten pasar parametros al constructor. - Inheritance - Portability, sistemas operativos diferentes a Windows no tienen registros. Lesson 2: Exponiendo componentes .NET a COM Para que componentes .NET sea consumidos por COM, se debe utilizar COM Callable Wrapper(CCW) Para realizar todo esto, se deben seguir los sgtes pasos: 1. Crear un library class .NET 2. Abrir propiedades de proyecto 3. Clickear el tab Build 4. Seleccionar Register For COM Interop 5. Build a la aplicacion Escondiendo clases .NET de COM Para nivelar la visibilidad, se utiliza el atributo ComVisible de la sgte forma: [assembly: ComVisible(false)] A cada miembro, una clase o metodo se le puede colocar el atributo de forma individial [Comvisible(true)] Apesar de que un assembly pueda ser creado visible para COM, MSDN da los sgtes tips: - Todas las clases deben usar un constructor por default sin parametros - Cualquier tipo que va a ser expuesto, debe de ser publico - Cualquier miembro a ser expuesto, debe ser publico - Clases abstractas no pueden ser consumidas Luego, para exponer el assembly, hay 2 formas: Compilarlo y luego utilizar Type Library Exporter Utility tlbexp midll.dll /out:nuevonombre.tlb Luego se necesita crear un script de recursos (mires.res) con la siguiente IDL: IDR_TYPELIB1 typelib "nuevonombre.tlb" Luego recompilar la aplicacion con el nuevo recurso adherido: csc /t:library ComVisiblePerson.cs /win32res:mires.res

Lesson 3: Usando codigo no administrado Platform Invoke es critico cuando necesitas llamar un no administrado Windows API. Se adminisra P/Invoke a traves del namespace System.Runtime.InteropServices. Para usar P/Invoke se hace lo sgte: 1. Crear un nuevo static external method con el nombre de la funcion que quieres llamar 2. Decorarla con el atributo DllImport especificando la libreria que debes llamar. 3. Llamar al metodo desde tu codigo Por ejemplo, para usar GetWindowsText del Windows API. class WindowsExample { private const int BufferSize =256; [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] private static extern Int32 GetWindowText(IntPtr hWnd, StringBuilder textValue, int counter); public static void GetScreenDemo() { StringBuilder builder = new StringBuilder(BufferSize); IntPtr handle = GetForegroundWindow(); if (GetWindowText(handle, builder, Buffersize)>0) Console.WriteLine(builder.ToString()); } } Encapsular funciones DLL Muchas veces conviene crear una clase que exponga y wrapee esta funcionalidad. Esto da los sgtes beneficios: - Los consumidores van a usar tu codigo como normalmente lo hacen - Esto quita el trabajo a los desarrolladores de tener que recordar los nombres de las funciones del API y sus respectivos parametros. - Esto va a ser menos inclinado a errores Un claro ejemplo es el GetScreenDemo(). Si es que uno tiene ya una clase con esa funcionalidad, solo va a tener que llamar al metodo sin preocuparse por conocer todo el API. Conversion de tipos de dato El primer mecanismo para convertie tipos de datos es el atributp MarshalAs, puede ser aplicacdo a una propiedad o parametro. Se usa de la sgte forma: class MarshalAsDemo{

[MarshalAs(UnmanagedType.LPStr)] public string firstName; public string LastName; [MarshalAs(UnmanagedType.Bool)] public Boolean IsCurrentlyWorkking; } Forma de aplicarlo a un parametro public String LastName([MarshalAs(UnmanagedType.LPStr) String lastName); Marshaling Structures Cuando un tipo es creado, el CLR va a decidir como organizar mejor los miembros de la clase. Para manualmente indicar al CLR sobre como manejar el disenho del tipo, el atributo System.Runtime.InteropServices.StructLayoutAttribute es proveido. Documentacion de StructLayoutAttribute: Campos publicos: - CharSet, indica como convertir los campos tipo cadena, LPWSTR o LPSTR. - Pack, controla el alineamiento de los campos de datos de una clase o estructura en memoria - Size, indica el tamanho absoluto de una clase o estructura Propiedades: - TypeId, cuando es implementada en una clase derivada, obtiene el identificador unico para este atributo - Value, obtiene el LayoutKind que especifica como la clase fue organizada. El atributo es lo mas importante, el constructor toma una de los sgtes 3 valores: - LayoutKind.Auto, el developer otorga todo el control al CLR - LayoutKind.Sequential, el CLR preserva todo lo especificado por el developer - LayoutKind.Explicit, el CLR usara el layout explicitamente especificado por el developer usand memory offsets. Layout.Sequential Este metodo indica que los valores de la estructura van a aparecer exactamente como ellos estan en la llamada a la libreria: [StructLayout(LayoutKind.Sequential)] class OSVersionInfo { public int dwOSVersionInfoSize; public int dwMajorVersion; public int dwMinorVersion; public int dwBuildNumber; public int dwPlatformId; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] public string szCSDVersion; }

Layout.Explicit Con este metodo, 2 cosas deben ser hechas: - LayoutKing debe de ser Explicit - El offset en bytes debe ser especificado por cada campo [StructLayout(LayoutKind.Explicit)] class OSVersionInfo { [FieldOffset(0)] public int dwOSVersionInfoSize; [FieldOffset(4)] public int dwMajorVersion; [FieldOffset(8)] public int dwMinorVersion; [FieldOffset(12)] public int dwBuildNumber; [FieldOffset(16)] public int dwPlatformId; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] [FieldOffset(20)] public string szCSDVersion; } Usando callback con codigo no administrado Para esto usaremos objetos Delegate de la sgte forma: 1. Crear un objeto Delegate con la misma firma que el callback 2. Substituir el Delegate por el callback y hacer la llamada. ejemplo: public delegate Boolean Democallback(IntPtr hWnd, Int32 lParam); private const String referencia = "user32.dll"; private const Int32 buffer = 100; [DllImport(referencia)] public static extern Int32 EnumWindows(Democallback callback, Int32 param); [DllImport(referencia)] public static extern Int32 GetWindowsText(IntPtr hWnd, StringBuilder lpString, Int32 nMaxCount); public static Boolean DisplayWindowText(IntPtr hWnd, Int32 lParam) { StringBuilder builder = new StringBuilder(buffer); if (GetWindowText(hWnd, builder, buffer) !=0) Console.WriteLine(builder.ToString()); return true; } public static void RunDemo(){ EnumWindows(DisplayWindowInfo, 0); }

Limitaciones de codigo no administrado - Performance, la interoperacion de codigo es menos eficiente que lo de .Net. - Type safety, Codigo no administrado es a veces no seguro. Esto puede traer implicancias, como problemas de lectura, seguridad, etc. - Code security, seguridad declarativa no va a ser disponible en codigo no administrado, por lo que tu codigo va a ser forzado a acomodar esta consistencia. - Versioning, no existe control de esto, por lo que la ejecucion del codigo puede no darse con exito en otro sitio. Capitulo 14 Reflexion Lesson 1 Entendiendo reflexion Entendiendo Assemblies y Modulos Un assembly es un contenedor logico para diferentes partes de datos que el CLR necesita ejecutar. Esas partes son: - Assembly metadata, incluye data que define al assembly, como nombre, version, strong name y culture information. Es llamado manifest - Type metadata, incluye namespaces y nombres de tipos, miembros individuales de un tipo (metodos, propiedades, constructores) y sus parametros. - Code(Intermediate Language code) - Resources, son objetos como cadenas, imagenes o archivos Uno puede separar un assembly en varios assemblies, pero el assembly metadata debe estar en el assembly principal. Modulos son contenedores de tipos que contienen un assembly. Se va a utilizar muchos modulos solo cuando se necesite hacer cosas como intercambiar fuentes de lenguaje con u simple assembly o proveer soporte para modular downloading de modulos. VS no soporta multiples modulos por assembly. Por lo que debe ser hecho desde lineas de comandos. Clase Assembly Metodos: - GetAssembly, retorna un Assembly que contiene un tipo especifico - GetCallingAssembly, retorna un Assembly que contiene el codigo que llamo al metodo actual. - GetEntryAssembly, retorna el Assembly que contiene el codigo que inicio el proceso actual - GetExecutingAssembly, retorna el Assembly que contiene al codigo que se ejecuta actualmente - Load, carga un Assembly en el AppDomain - LoadFile, carga un Assembly especificando su Path - LoadFrom, Carga un Assembly en el actual AppDomain localizado en un path especifico - ReflectionOnlyLoad, carga un Assembly, pero permite interrogacion del assembly. - ReflectionOnlyLoadFrom, carga un Assembly localizado en un path, pero permite interrogacion del assembly

Una vez que se tiene una instancia de Assembly, se puede interrogar a sus propiedades sobre el assembly. Propiedades: - EntryPoint, devuelve el metodo que representa el primer codigo ejecutado en un assembly - FullName, nombre completo del assembly - GlobalAssemblyCache, devuelve un valo indicando si el assembly fue cargado desde el GAC - Location, obtiene el path del assembly - ReflectionOnly, indica si el assembly fue cargado solo para reflexion - CreateInstance, crea una instancia de un tipo especifico que existe en el assembly - GetCustomAttributes, devuelve un arreglo de atributos del assembly - GetExportedTypes, devuelve una coleccion de tipos que son publicamente visibles - GetFile, devuelve un FileStream object de un file contenida en el assembly - GetFiles, devuelve un arreglo de objetos FileStream que representan todas las filas contenidas en el assembly - GetLoadedModules, devuelve un arreglo de los modulos cargados actualmente en el assembly - GetModule, devuelve un modulo especifico - GetModules, devuelve todos los modulos del assembly - GetName, devuelve un objeto AssemblyName - GetSatelliteAssembly, devuelve un satellite assembly de una cultura especifica si existe - GetTypes, devuelve un arreglo de todos los tipos definidos en todos los modulos del assembly - IsDefined, devuelve un valor que indica si un atributo esta definido en el assembly A veces se necesita un assembly para leer su informacion, pero no para ejecutarlo o crear tipos. Para hacer este proceso mas eficiente, la clase Assembly soporta ReflectionOnlyLoad y ReflectionOnlyLoadFrom, estos metodos devuelven una instancia de Assembly, pero no soporta ciertos metodos cmo CreateInstance. Las propiedades de la clase Module, son: - Assembly, obtiene el Assembly en el cual reside el modulo - FullyQualifiedName, obtiene el nombre completo del modulo, incluyendo el path - Name, solo da el nombre del modulo Metodos: - FindTypes, busca los tipos que concuerden con cierto criterio - GetCustomAttributes, obtiene los atributos asociados con el modulo - GetField, devuelve un especifico campo en el modulo - GetFields, obtiene todos los campos en el modulo - GetMethod, obtiene un metodo - GetMethods, obtiene todos los metodos - GetTypes, devuelve todos los tipos en el modulo

- IsResource, usado para determinar si ciertos objetos son recursos del modulo

Lesson 2 Atributos del assembly Atributos del assembly pueden proveer informacion adicional acerca del assembly. Normalmente se adhiere informacion en el AssemblyInfo.cs. [assembly : AssemblyCompany("Mipi producciones")] El nombre del atributo es el mismo que la clase atributo. Por ejemplo la clase AssemblyCompanyAttribute representa el atributo AssemblyCompany mostrado en el codigo anterior. Clase AssemblyAlgorithmIdAttribute Especifica cual algoritmo hash se utilizo cuando se leia el hash en el manifest del assembly: [assembly : AssemblyAlgorithmId(AssemblyHashAlgorithm.MD5)] Clase AssemblyCompanyAttribute Especifica la companhia que produjo el assembly. Es usado por el compilador para poner ese nombre en la cabecera del .DLL [assembly : AssemblyCompany("mipi producciones")] Clase AssemblyConfigurationAttribute Especifica la configuracion del assembly, "DEBUG" o "RELEASE" [assembly: AssemblyConfiguration("DEBUG")] Clase AssemblyCopyright Es usada para especificar el copyright del assembly: [assembly : AssemblyCopyright("Copyright")] Clase AssemblyCultureAttribute Especifica la cultura del assembly. [assembly : AssemblyCulture("de")] clase AssemblyDefaultAliasAttribute Usado para simplifiar el nombre de un assembly [assembly : AssemblyDefaultAlias("DataLayer")] Clase AssemblyDelaySignAttribute Especifica que el assembly va a ser firmado despues de la compilacion pero va a ser marcada como strong assembly. Si se especifica, debe dar un AssemblyKeyFile attribute para especificar una llave temporal [assembly : AssemblyDelaySign(true)]

Clase AssemblyDescriptionAttribute Usado para anotar descripcion del assembly [assembly : AssemblyDescription("descripcion")] Clase AssemblyFileVersionAttribute Especifica la version del archivo del assembly [assembly : AssemblyFileVersion("1.0.0.0")] Clase AssemblyFlagsAttribute Es usado para especificar uno o mas valores de AssemblyNameFlags al assembly. Los cuales son: - EnableJITcompileOptimizer, habilita Just in time optimizacion de compilacion - EnableJITcompileTracking, habilita JIT compiler tracking - None, ningun flag - PublicKey, permite creacion de llave publica del assembly - Retargetable, permite al assembly, re-senhalar a un assembly de un diferente publisher [assembly : AssemblyFlags(AssemblyNameFlags.EnableJITcompileOptimizer | AssemblyNameFlags.EnableJITcompileOptimizer)] Clase AssemblyInformationalVersionAttribute Especifica version que es usada para propositos de informacion [assembly : AssemblyInformationalVersion("1.0.0.1")] Clase AssemblyKeyFileAttribute Especifica la ruta a un archivo key para usar para firma. El sn.exe del framework puede ser usado para crear un key file [assembly : AssemblyKeyFile("../key.snk")] Clase AssemblyTitleAttribute Especifica un titulo para el assembly en el manifest [assembly : AssemblyTitle("Titulo")] Clase AssemblyTrademarkAttribute Especifica cualquier informacion trademark acerca del assembly [assembly : AssemblyTrademark("Marca")] Clase AssemblyVersionAttribute La version del assembly esta hecha de 4 elementos separados por periodo <major version>.<minor version>.<build number>.<revision> 1.2.3.4 AssemblyVersion pemrite reemplazar los build number y revision con un asterisco. Usando el asterisco le dices al compilador actualizar el

builder number y revision con un valor autogenerado. Este autogenerado se incremente por dia. Si se especifica un revision number, no se puede usar un asterisco para el build number. El autogenerado del build es incremental, mientras que el de revision es random [assembly : AssemblyVersion("1.2.*.*")] Llamando al metodo GetCustomAttributes se obtiene los atributos de un assembly. La interfaz ICustomAttributeProvider es usada para encontrar que tipo de objetos provee un custom attribute. Debido a esto, el metodo GetCustomAttribute recibe u booleano para indicar si se desea tener los atributos heredados. Pero debido a que el metodo esta en la clase Assembly, el framework ignora el valor booleano. (no hay arbol de herencia para assemblies) Assembly a = Assembly.GetExecutingAssembly(); object[] attrs = a.GetCustomAttributes(false); foreach (Attribute attr in attrs) { console.WriteLine(attr.GetType().Name); } En caso se desee obtener un especifico tipo de atributo se hace: Type attype = typeof(AssemblyDescriptionAttribute); object[] attrs = a.GetCustomAttributes(attype, false); Lesson 3 Tipos de reflexion Obteniendo types Formas de obtener un objeto type: - Desde una clase Assembly - Desde una clase Module - Desde una instancia de un object - Usando la palabra typeof en C# //Assembly Assembly a = Assembly.GetExecutingAssembly(); //obteniendo los tipos Type[] assemblyTypes = a.GetTypes(); //Module Module[] mods = a.GetModules(); Module m = mods[0]; Type[] moduleTypes = m.GetTypes(); //Object object o = new object(); Type objType = o.GetType(); //typeof

Type tipo = typeof(Int32); Propiedades principales de la clase Type: - Assembly, obtiene el assembly asociado - Attributes, atributos del type - BaseType, type base - HasElementType, indica si es un arreglo de otro type - IsSealed, indica si el Type no puede ser heredado - Module, obtiene el Module donde reside el Type - Namespace Metodos de Type - GetConstructor, devuelve un ConstructorInfo asociado al Type - GetConstructors Una forma de usar el Type foreach (Attribute attr in t.GetCustomAttributes(false)) { console.WriteLine(attr.GetType().Name); }

Enumerando miembros de la clase FieldInfo, EventInfo, etc. derivan de MemberInfo foreach (PropertyInfo prop in t.GetProperties()) { Console.WriteLine(prop.Name); }

foreach (Type nestedType in t.GetNestedTypes()) { Console.WriteLine(nestedType.Name); } foreach (MemberInfo member in t.GetMembers()) { Console.WriteLine(member.MemberType, member.Name); } Clases derivadas de MemberInfo - ConstructorInfo - EventInfo - FieldInfo - LocalVariableInfo, representa una variable local dentro del cuerpo de un metodo

- MethodBase, representa cualquier miembro que contiene codigo, incluye metodos y constructores, es actualmente la clase base para ConstructorInfo y MethodInfo - MethodInfo - PropertyInfo - Type Para ver a que tipo pertenece: if (member.MemberType == MemberTypes.Property) { PropertyInfo prop = (PropertyInfo)member; Console.WriteLine(prop.PropertyType.Name); } Enumerando a traves de los miembros de un Type, solo se van a listar los miembros publicos Entendiendo el MethodBody MethodBody es como un contenedor que contiene las variables locales y el actual Intermediate Language (IL) instructions, que son compiladas en el code machine en tiempo de ejecucion. Se puede obtener de esta forma: MethodBody body = meth.GetMethodBody(); Console.WriteLine(body.MaxStackSize); foreach (LocalVariableInfo local in body.LocalVariables) { Console.WriteLine(local.LocalType + " " + local.LocalIndex); } Los nombres de las variables locales no son guardados, solo es guardado su orden. Finalmente, se puede obtener el IL como un arreglo de bytes foreach(Byte b in body.GetILAsByteArray()) { Console.Write("{0:x2}", b); } BindingFlags Este enumerador es usado para controlar como los miembros de un tipo son devueltos usando el GetMembers. Valores: - DeclaredOnly, miembros declarados directamente en el type, son incluidos. Miembros heredados son ignorados. - Default, sin flags - FlattenHierarchy, declarados y heredados miembros son retornados - IgnoreCase, match con case insensitive es usado - Instance, miembros que son parte de una instancia de type van a ser incluidos - NonPublic, miembros que no son publicos - Public, miembros que son publicos

- Static, miembros que son estaticos Type t = typeof(String); //Especifica publicos y no publicos, pero solo instance members BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; MemberInfo[] members = t.GetMembers(flags); foreach (MemberInfo member in members) { Console.WriteLine(member.Name); }

Lesson 4 Escribiendo codigo dinamico El sistema de reflexion permite crear objetos dinamicamente, incluso desde assemblies que no se han referenciado a tiempo. Esto es mas dificil que escribir codigo chequeado por el compilador de tipo seguro. Creando objetos de forma dinamica: string path = @"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\" + "mscorlib.dll"; //Obtiene el assembly Assembly a = Assembly.LoadFile(path); //Obtiene el tipo hashtable Type hashType = theAssembly.GetType("System.Collections.Hashtable"); Una vez que se tiene el tipo, se puede preguntar por el ConstructorInfo para usar el constructor de un nuevo tipo: Type[] argumentos = Type.EmptyTypes; //Constructor vacio ConstructorInfo ctor = hashType.GetConstructor(argumentTypes); //Si se quiere un constructor con argumentos: Type[] argumentos = new Type[]{typeof(int)} ConstructorInfo ctor = hashType.GetConstructor(argumentTypes); Llamando al constructor object newHash = ctor.Invoke(new object[] {}); Invocando miembros: MethodInfo meth = hashType.GetMethod("Add"); meth.Invoke(newHash, new object[]{"hi","hello"});

Obteniendo cantidad de miembros PropertyInfo prop = hashType.GetProperty("Count"); int count = (int)prop.GetValue(newHash, null); Invocando miembros estaticos No todo el codigo dinamico requiere que se tenga una instancia de una clase. Cuando se necesita llamar miembros estaticos, uno se salta la creacion de un objeto Type consoleType = typeof(Console); MethodInfo write = consoleType.GetMethod("WriteLine", new Type[]{typeof(string)}); write.Invoke(null, new Object[]{count.ToString()}); recibe null porque es un metodo estatico Clase Binder Es responsable de determinar como hacer conversiones de tipos y donde localizar codigo dinamico. Una instancia de Binder es argumento opcional para los metodos de la clase Type que retornan miembros de un type.

Lesson 5: Creando codigo en tiempo de ejecucion Construyendo tu propio codigo El sistema de reflexion incluye un sub-namespace llamado Emit (System.Reflection.Emit) que contiene un set de constructor de clases que son usadas para construir assemblies, types, metodos, y demas. Para contruir codigo en tiempo de ejecucion, se tiene que encapsular como cualquier otro codigo. Clases Builder, cuyo rol es crear codigo a tiempo de ejecucion: - AssemblyBuilder - ConstructorBuilder - EnumBuilder - EventBuilder - FieldBuilder - LocalBuilder - MethodBuilder - ModuleBuilder - ParameterBuilder - PropertyBuilder - TypeBuilder Creando un Assembly y un Modulo Primero solicitar al AppDomain crear un assembly dinamico, el AppDomain tiene un metodo DefineDynamicAssembly que toma como parametros un AssemblyName y un AssemblyBuilderAccess. AssemblyName name = new name.Name = "Assembly"; AssemblyName();

AssemblyBuilderAccess especifica que puedes hacer con el nuevo assembly dinamico. Puedes especificar ReflectionOnly, Run, Save o RunAndSave. AssemblyBuilder builder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave); Ahora con el AssemblyBuilder, se puede crear un ModuleBuilder. ModuleBuilder modBuilder = builder.DefiineDynamicModule("NombreModulo", "assembly.dll"); Definiendo un Type Creando un type dinamico, comienza llamado al metodo DefineType de la clase ModuleBuilder. Este metodo recibe un nombre para el type y un valor del enumerador TypeAttributes. este ultimo especifica opciones para el type. TypeBuilder typeBuilder = modBuilder.DefineType("NuevoTipo", TypeAttributes.Public | TypeAttributes.Class); Se le puede anhadir un tercer parametro que indique la clase base y un cuarto parametro que contiene un arreglo de tipos que definen las interfaces implementadas en el tipo: TypeBuilder typeBuilder = modBuilder.DefineType("NuevoTipo", TypeAttributes.Public | TypeAttributes.Class, typeof(Hashtable), new Type[]{typeof(IDisposable)}); Creando miembros El TypeBuilder tiene metodos que ayudan a definir los miembros de un type: - DefineConstructor - DefineDefaultConstructor - DefineEvent - DefineField - DefineGenericParameters - DefineMethod - DefineMethodOverride - DefineNestedType - DefinePInvokeMethod - DefineProperty ConstructorBuilder ctorBuilder = typeBuilder.DefineDefaultConstructor(MethodAttributes.Public); ILGenerator es una clase usada para generar variables locales y codigo IL. ILGenerator codeGen = ctorBuilder.GetILGenerator(); codeGen.Emit(OpCodes.Ret);

El metodo Emit inserta una nueva linea de codigo IL en el constructor. La clase OpCodes expone IL OpCodes como un separado miembro estatico, especifica el codigo IL para retornar. MethodBuilder methBuilder = typeBuilder.DefineMethod("Add", MethodAttributes.Public, null, new Type[]{typeof(string)}) //Tercer parametro es el tipo de retorno //Cuarto parametro es el tipo de parametro Para definir metodos estaticos: MethodBuilder methBuilder = typeBuilder.DefineMethod("Add", MethodAttributes.Public | MethodAttributes.Static, null, new Type[]{typeof(string)}) Para crear un campo llamado "mipi" FieldBuilder fieldBuilder = typeBuilder.DefineField("mipi", typeof(int), FieldAttributes.Private); Para adherir propiedad: PropertyBuilder propBuilder = typeBuilder.DefineProperty("Mipi", PropertyAttributes.None, typeof(int), type.EmptyTypes); Otra forma MethodAttributes getAttributes = MethodAttributes.Public | MethodAttributes.Specialame | MethodAttributes.HideBySig; MethodBuilder propGetBuilder = typeBuilder.DefineMethod("get_Mipi", getAttributes, typeof(int), type.EmptyTypes); Entonces se puede asociar a la propiedad propBuilder.SetGetMethod(propGetBuilder); Para persistirlo en disco, se hace: builder.Save("assembly.dll"); Capitulo 15 Mail El enviar mail tiene 2 pasos: 1. Crear el mensaje del mail 2. Enviar el mensaje a un servidor SMTP Lesson 1 Creando un mensaje de mail De la forma mas simple, un mensaje de mail tiene un sender, recipient, subject y body. Pero tb puede tener tipo de codificacion, multiples vistas para texto plano y HTML, attachments e imagenes embebidas dentro del HTML. Proceso para crear y enviar un mensaje de mail: 1. Crear un objeto MailMessage. 2. Si no se especifica un recipient en el constructor del objeto, adherirlo a MailMessage

3. Si se necesita proveer multiples vistas, crear objetos AlternateView y adherirlos al objeto MailMessage 4. Si es necesario, crear uno o mas objetos Attachment y adherirlos al objeto MailMessage 5. Crear un objeto SmtpClient y especificarle el servidor SMTP 6. Si el servidor SMTP requiere clientes para autenticar, adherirle las credenciales al objeto SmtpClient 7. Pasarle el MailMessage al metodo SmtpClient.Send. De forma alterna, se puede usar SmtpClient.SendAsync para enviarlo de forma asincrona. Creando un objeto MailMessage MailMessage tiene 4 constructores diferentes. MailMessage m = new MailMessage("sender@hotmail.com","mipi@gmail.com","subject","body"); Para especificar el sender y recipient, se puede usar el objeto MailAddress que especifica el mail, nombre a mostrar y tipo de codificacion MailMessage m = new MailMessage(new MailAddress("sender@hotmail.com","sender"),new MailAddress("recipient@hotmail.com","recipient") ); Otra forma de usar si es que uno necesita especificar mas de un destinatario: MailMessage m = new MailMessage(); m.From = new MailAddress("sender@hotmail.com","sender"); m.To.Add(new MailAddress("recipient1@hotmail.com","recipient1")); m.To.Add(new MailAddress("recipient2@hotmail.com","recipient2")); m.To.Add(new MailAddress("recipient3@hotmail.com","recipient3")); m.Subject = "subject"; m.Body = "Body"; MailMessage tiene las sgtes propiedades: - DeliveryNotificationOptions, indica al servidor SMTP para enviar un mensaje a la direccion especificada en MailMessage.From para indicar si el mensaje fallo, tuvo exito o fue enviado a otro servidor. Para esto se usa el enumerador DeliveryNotificatiOnptions y los valores son OnSuccess, OnFailure, Delay, None y Never. - ReplyTo, la dirreccion email que replica va ser enviada. Se debe setear MailMessage.From como la direccion que debe recibir replica en vez de ReplyTo. - Priority, indica la prioridad del mensaje. Se usa un enumerador para esto MailPriority y tiene los valores Normal, High y Low. Attachear archivos Para atachear un archivo, se usa el metodo MailMessage.Attachments.Add MailMessage m = new MailMessage(); m.Attachments.Add(new Attachment(@"C:\boot.ini")); Ademas se puede especificar un MIME(Multipurpose Internet Mail Extensions) usando el enumerador System.Net.Mime.MediaTypeNames

MailMessage m = new MailMessage(); Stream sr = new FileStream(@"C:\Boot.ini", FileMode.Open, FileAccess.Read); m.Attachments.Add(new Attachment(sr, "myfile.txt", MediaTypeNames.Application.Octet)); El Octet es pa indicar texto e imagenes. Como crear mails HTML Se tiene que setear MailMessage.IsBodyHtml a true y el body del message debe ser en tags HTML. MailMessage m = new MailMessage(); m.From = new MailAddress("sender@hotmail.com", "sender"); m.To.Add(new MailAddress("recipient@hotmail.com","recipient"); m.Subject = "testing html"; m.Body = "<html><body><h1>Mensaje</h1><br>This is an html message.</body></html>"; m.IsBodyHtml = true; //Enviando el mensaje SmtpClient client = new SmtpClient("smtp.contoso.com"); client.Send(m); Para embeber imagenes dentro del mensaje HTML, se deberian usar las clases AlternateView y LinkedResource. Primero se crea un mensaje HTML usando AlternateView y entonces se adhiere imagenes usando LinkedResource. Ejemplo: //Referencia a las imagenes embebidas usando el id del contenido string html = "<html><body><h1>Picture</h1><br><img src=\"cid:Pic\"></body></html>"; AlternateView avHtml = AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html); //Crear un LinkedResource para embeber imagen LinkedResource pic = new LinkedResource("pic.jpg",MediaTypeNames.Image.Jpeg); pic.ContentId = "Pic"; avHtml.LinkedResources.Add(pic); //Crear una vista alternativa para clientes no soportados string texto = "Debes usar un cliente que soporte html"; AlternateView avText = AlternateView.CreateAlternateViewFromString(textBody, null, MediaTypeNames.Text.Plain); //Adherir las alternativas de vista en vez de usar el MailMessage.Body

MailMessage m = new MailMessage(); m.AlternateViews.Add(avHtml); m.AlternateViews.Add(avText); m.From = new MailAddress("sender@hotmail.com", "sender"); m.To.Add(new MailAddress("recipient@hotmail.com","recipient"); m.Subject = "picture html"; //Enviando el mensaje SmtpClient client = new SmtpClient("smtp.contoso.com"); client.Send(m); Lesson 2 Enviando un mail En .Net, la clase SmtpClient representa al servidor SMTP. Ejemplo: MailMessage m = new MailMessage("sender@hotmail.com","mipi@gmail.com","subject","body"); SmtpClient client = new SmtpClient("smtp.contoso.com"); client.Send(m); Muchas cosas pueden ir mal cuando se envia un mail, smtp no disponible, malas credenciales, etc. En esas circunstancias se arrojara una excepcion y la aplicacion debe estar preparada para capturarla. En este caso se da un SmtpException cuando el servidor smtp no se encuentra, el servidor identifico el mensaje como spam o el servidor requiere un username y password. Tb puede arrojar SmtpFailedRecipientException cuando el servidor SMTP rechaze un recipient. Tb podemos tener: - InvalidOperationException, no se definio el hostname del servidor Configurando credenciales: Servidores SMTP proveidos por ISPs determinan si un usuario es autoirzado basado en las direcciones IP. Si se es parte de la red ISP, entonces se esta permitido a usar el servidor SMTP. Otros servidores SMTP requieren username y password. Para usar las credenciales de red por default, setear SmtpClient.UseDefaultCredentials a True. O sino, setear SmtpClient.Credentials a CredentialCache.DefaultNetworkCredentials. Ejemplo: SmtpClient client = new SmtpClient("smtp.contoso.com"); client.Credentials = CredentialCache.DefaultNetworkCredentials; Si se necesita especificar username y password, se crea una instancia de System.Net.NetworkCredential y se define SmtpClient.Credentials. SmtpClient client = new SmtpClient("smtp.contoso.com"); client.Credentials = new NetworkCredential("user","password");

Como configurar SSL Otra propiedad importantes es SmtpClient.EnableSsl. Cuando se setea a True, el runtime va encriptar la comunicacion usando SSL. OJO, no todos los servidores SMTP soportan SSL. Como enviar un mensaje asincronamente La mayoria de veces el enviar un mensaje toma menos de un segundo, pero algunas veces el servidor SMTP puede ser lento e irresponsable, causando que la aplicacion espere por el valor especificado en SmtpClient.Timeout(por default 100 segundos). Para realizar el envio de forma asincrona se debe de hacer: 1. Crear un metodo para responder al evento SmtpClient.SendCompleted. Este metodo necesita determinar si la transmision fue exitosa, no exitosa o cancelada. 2. Adherir un manejador de eventos a SmtpClient.SendCompleted 3. Llamar a Smtpclient.SendAsync 4. Opcionalmente, proveer al usuario la oportunidad de cancelar el email, llamando al metodo SmtpClient.SendAsyncCancel Ejemplo: void sc_SendCompleted(object sender, AsyncCompletedEventArgs e) { if (e.Cancelled) Console.WriteLine("Mensaje cancelado"); else if (e.Error != null) Console.WriteLine("Mensaje con error debido a " + e.Error.ToString()); else Console.Writeline("Mensaje enviado"); } sc = new SmtpClient("server_name"); //Adherir el evento sc.SendCompleted += new SendCompletedEventHandler(sc_SendCompleted); /Enviar el mensaje de forma asincrona sc.SendAsync(mm, null); //Cancelar el envio sc.SendAsyncCancel(); SmtpClient.SendAsync acepta 2 parametros, el mensaje y un Object generico. Capitulo 16 Lesson 1 La clase CultureInfo nos ofrece: - Control de cmo los strings van a ser comparados. - Control de cmo los numeros son comparados y sus formatos - Control de cmo las fechas son comparadas y sus formatos - Control de cmo los recursos son devueltos y usados.

Una cultura va a ser agrupada en una de las sgtes categorias: - Invariant Culture, Es una cultura insensitive. Es usada por ejemplo para casos de aplicaciones trial que deben verificar la fecha sin importarles la fecha que est dentro de la computadora. - Neutral Culture, es el lenguaje a utilizar, English (en), French (fr) y Spanish(sp), son culturas neutrales. No tiene relacin a un pais o regin. - Specific Culture, es la ms precisa de las 3, pues especifica el lenguaje y el pais o regin. fr-FR, en-US, etc. Para detectar la informacin culturas actual se hace: CultureInfo userCulture = Thread.CurrentThread.CurrentCulture; Console.WriteLine(userCultue.Name); Console.WriteLine(userCultue.DisplayName); Console.WriteLine(userCultue.NativeName); //Usando el formateador, va a generar que el cambio de CurrentCulture va a ser propagado en todo lo relacionado. tbSalary.Text = (10000).ToString("C"); CurrentUICulture es la propiedad de la clase CultureInfo, que a veces es la misma propiedad CurrentCulture de CultireInfo. Se podra usar una cultura para calculos y manipulacion interna y otra puede ser usada para mostrar cosas. Ejemplo CultureInfo userCulture = Thread.CurrentThread.CurrentUICulture; Console.WriteLine(userCulture.Name); Para cambiar el CurrentCulture: CultureInfo userCulture = Thread.CurrentThread.CurrentCulture; Console.WriteLine(userCulture.Name); //Cambiamos a espaol Per Thread.CurrentThread.CurrentCulture = new CultureInfo("es-VE"); Console.WriteLine(Thread.CurrentThread.CurrentCulture); La clase CultureInfo adems nos da una forma de detectar la informacion de la cultura del usuario, mediante el metodo GetCultures. Este metodo toma como parametro un objeto CultureType. CultureType es un enumerador que posee los sgtes valores: - AllCultures, refiere a todas las culturas disponibles - FrameworkCultures, se refiere a la cultura neutral y especfica incluidas en el framework - InstalledWin32Cultures, incluye todas las culturas instaladas en el sistema operativo - NeutralCultures, incluye todas las culturas asociadas a un lenguaje - ReplacementCultures, incluye culturas customizadas por el usuario que reemplazan las que vienen en el framework. - SpecificCultures, incluye cultures especificas para un pais o region - UserCustomCulture, incluye culturas customizadas creadas por el usuario - WindowsOnlyCultures, incluye culturas instaladas en windows, pero no en el framework.

ejemplo: foreach (CultureInfo userCulture in CultureInfo.GetCultures(CultureTypes.SpecificCultures)){ Console.WriteLine(userCulture.Name); } clase RegionInfo Es una clase que provee informacin ms detallada sobre una cultura. En s, provee informacin acerca de un pais o region en particular. CultureInfo tiene 2 ipos de propiedades que te permiten trabajar en cojunto con RegionInfo: Identificadores nominales e identificadores numricos. CultureInfo userCulture = Thread.CurrentThread.CurrentCulture; RegionInfo region = new RegionInfo(userCulture.LCID); o sino RegionInfo region = new RegionInfo(UserCulture.Name); Luego se puede acceder a sus propiedades: region.EnglishName region.DisplayName region.CurrencySymbol Clases DateTimeFormatInfo y NumberFormatInfo Uno normalmente asume: - Las fechas y formatos de fechas son los mismos en cualquier lugar de la aplicacion - Los numeros y formatos de estos son los mismos - Valores actuales van a ser los mismos a traves de otros paises. Las clases mencionadas, manejan las diferencias entre paises. DateTimeFormatInfo provee metodos y propiedades para manejar y responder a fechas de diferentes culturas.ejm: CultureInfo userCulture = new CultureInfo("es-VE"); String[] days = UsersCulture.DateTimeFormat.DayNames; foreach (string day in days){ Console.WriteLine(day); } Y para meses: CultureInfo userCulture = new CultureInfo("es-VE"); String[] months = UsersCulture.DateTimeFormat.MonthNames; foreach (string month in months){ Console.WriteLine(month); }

Y la forma de usar NumberFormatInfo: CultureInfo userCulture = new CultureInfo("es-VE"); Console.WriteLine(userCulture.NumberFormat.CurrencySymbol); Console.WriteLine(userCulture.NumberFormat.NumberDecimalSeparator);

Usando los enumeradores CompareInfo y CompareOptions Una de las razones de usar CultureInfo es el poder comparar cadenas a nivel cultural. Por ello, la clase tiene una propiedad CompareInfo, la cual se puede obtener y setear. CompareInfo info = Thread.CurrentThread.CurrentCulture.CompareInfo; Console.WriteLine(info.Name); Console.WriteLine(info.LCID); Comparaciones son tipicamente basadas en una cultura especifica. CompareInfo info = new CultureInfo("en-US").CompareInfo; Console.WriteLine(info.Name); Console.WriteLine(info.LCID); El metodo mas util de CompareInfo es Comparer. string first = "Cote"; string second = "cote"; CompareInfo info = new CultureInfo("fr-FR").CompareInfo; info.Compare(first, second); El enumerador CompareOptions es utilizado para controlar el como la comparacion es realizada. Tiene los sgtes valores: - IgnoreCase, no tiene case sensitive - IgnoreKanaType, indica que la comparacion de cadenas va a ignorar el tipo Kana. - IgnoreNonSpace, indica que la comparacion debe ignorar los espacios en blanco de caracteres combinados. - IgnoreSymbols, indica que la comparacion debe ignorar simbolos, tales como espacios en blanco, puntuacion, simbolo de porcentaje, etc. - None, indica las opciones por default - Ordinal, indica que la comparacion de strings debe de ser echa usando los valores Unicode. - OrdinalIgnoreCase, indica ignorar el case sensitive y usa el invariant culture. - StringSort, indica que la comparacion debe usar el algoritmo de ordenr el string string first = "Cote"; string second = "cote"; CompareInfo info = new CultureInfo("fr-FR").CompareInfo; info.Compare(first, second, CompareOptions.IgnoreCase);

Lesson 2 Crear un custom culture La clase CultureRegionAndInfoBuilder permite crear y utilizar custom cultures. Ademas, permite instalar esta cultura en cualquier maquina. Se puede crear uno desde cero, basado en uno, o usar totalmente uno. CultureAndRegionInfoBuilder builder = new CultureAndRegionInfoBuilder("en-US", CultureAndRegionModifiers.Neutral); Se puede usar un existente RegionInfo, un objeto CultureInfo o ambos para popular un CultureAndRegionInfoBuilder. CultureInfo usCulture = new CultureInfo("en-US"); RegionInfo usRegion = new RegionInfo("US"); CultureAndRegionInfoBuilder builder = new CultureAndRegionInfoBuilder("enUS",CultureAndRegionModifiers.Neutral); builder.LoadDataFromCultureInfo(usCulture); builder.LoadDataFromRegionInfo(usRegion); Para crear una totalmente customizada basada en una: CultureInfo usCulture = new CultureInfo("en-US"); RegionInfo usRegion = new RegionInfo("US"); CultureAndRegionInfoBuilder builder = new CultureAndRegionInfoBuilder("en-USMicrosoft",CultureAndRegionModifiers.None); builder.LoadDataFromCultureInfo(usCulture); builder.LoadDataFromRegionInfo(usRegion); Valores del enumerador CultureAndRegionModifiers: - Neutral, neutral custom culture - None, especifico, supplemental custom culture - Replacement, custom culture que reemplaza una existente cultura del framework o local de Windows. (es especifico poner en lugar pra escenarios donde completamente sobreescribes valores y creas tu propia cultura) Aparte de esto, se le puede asignar a nuestro nuevo culture, su numberFormat y du DateFormat. Si se tiene una cultura, pero no region, deberia especificarse neutral Si se va a especificar informacion supplemental para el objeto, deberia especificarse None.

Você também pode gostar