Вы находитесь на странице: 1из 27

Tutorial

El siguiente ejemplo muestra dos enfoques diferentes para utilizar los argumentos de lnea de comandos que se pasan a una aplicacin. Ejemplo 1 Este ejemplo muestra cmo imprimir los argumentos de la lnea de comandos.
// cmdline1.cs // arguments: A B C using System; public class CommandLine { public static void Main(string[] args) { // The Length property is used to obtain the length of the array. // Notice that Length is a read-only property: Console.WriteLine("Number of command line parameters = {0}", args.Length); for(int i = 0; i < args.Length; i++) { Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]); } } }

Resultado Ejecute el programa con algunos argumentos como los siguientes: cmdline1 A B C. El resultado ser:
Number Arg[0] Arg[1] Arg[2] of command line parameters = 3 = [A] = [B] = [C]

Ejemplo 2 Otro enfoque para iterar en la matriz consiste en utilizar la instruccin foreach como se indica en este ejemplo. La instruccin foreach se puede utilizar para iterar en una matriz o una clase de coleccin de .NET Framework. Proporciona un mtodo simple para iterar en las colecciones.
// cmdline2.cs // arguments: John Paul Mary using System; public class CommandLine2

{ public static void Main(string[] args) { Console.WriteLine("Number of command line parameters = {0}", args.Length); foreach(string s in args) { Console.WriteLine(s); } } }

Resultado Ejecute el programa con algunos argumentos como los siguientes: cmdline2 John Paul Mary. El resultado ser:
Number of command line parameters = 3 John Paul Mary

Matrices en general

En las matrices de C#, los ndices empiezan en cero. Las matrices de C# funcionan de forma similar a como lo hacen en la mayora de los lenguajes populares; existen, sin embargo, algunas diferencias que se deben conocer. Cuando se declara una matriz, los corchetes ([]) deben ir despus del tipo, no despus del identificador. Colocar los corchetes despus del identificador no es sintcticamente vlido en C#.
int[] table; // not int table[];

Otro detalle es que el tamao de la matriz no forma parte de su tipo, como ocurre en el lenguaje C. Esto permite declarar una matriz y asignarle cualquier matriz de objetos int, independientemente de la longitud de la matriz.
int[] numbers; // declare numbers as an int array of any size numbers = new int[10]; // numbers is a 10-element array numbers = new int[20]; // now it's a 20-element array

Declarar matrices

C# admite matrices de una dimensin, matrices multidimensionales (matrices rectangulares) y matrices de matrices (matrices escalonadas). El siguiente ejemplo muestra cmo declarar diferentes tipos de matrices:

Matrices unidimensionales:
int[] numbers;

Matrices multidimensionales:
string[,] names;

Matrices de matrices (escalonadas):


byte[][] scores;

La declaracin de matrices (como se muestra arriba) no crea realmente las matrices. En C#, las matrices son objetos (se explica ms adelante en este tutorial) cuyas instancias deben crearse. Los siguientes ejemplos muestran cmo crear matrices: Matrices unidimensionales:
int[] numbers = new int[5];

Matrices multidimensionales:
string[,] names = new string[5,4];

Matrices de matrices (escalonadas):


byte[][] scores = new byte[5][]; for (int x = 0; x < scores.Length; x++) { scores[x] = new byte[4]; }

Tambin se pueden utilizar matrices ms grandes. Por ejemplo, se puede utilizar una matriz rectangular de tres dimensiones:
int[,,] buttons = new int[4,5,3];

Incluso, se pueden combinar matrices rectangulares y escalonadas. Por ejemplo, el siguiente cdigo declara una matriz unidimensional que contiene matrices tridimensionales de matrices bidimensionales de tipo int:
int[][,,][,] numbers;

Ejemplo El siguiente es un programa completo en C# que declara y crea instancias de las matrices comentadas anteriormente.
// arrays.cs

using System; class DeclareArraysSample { public static void Main() { // Single-dimensional array int[] numbers = new int[5]; // Multidimensional array string[,] names = new string[5,4]; // Array-of-arrays (jagged array) byte[][] scores = new byte[5][]; // Create the jagged array for (int i = 0; i < scores.Length; i++) { scores[i] = new byte[i+3]; } // Print length of each row for (int i = 0; i < scores.Length; i++) { Console.WriteLine("Length of row {0} is {1}", i, scores[i].Length); } } }

Resultado
Length Length Length Length Length of of of of of row row row row row 0 1 2 3 4 is is is is is 3 4 5 6 7

Inicializar matrices

C# proporciona mtodos simples y sencillos para inicializar matrices en el momento de la declaracin encerrando los valores iniciales entre llaves ({}). Los siguientes ejemplos muestran diferentes modos de inicializar diferentes tipos de matrices.
Nota Si no inicializa una matriz en el momento de la declaracin, sus miembros se inicializan automticamente con el valor inicial predeterminado para el tipo de matriz. Adems, si declara la matriz como campo de un tipo, se establecer con el valor predeterminado null cuando cree la instancia del tipo.

Matrices unidimensionales
int[] numbers = new int[5] {1, 2, 3, 4, 5}; string[] names = new string[3] {"Matt", "Joanne", "Robert"};

El tamao de la matriz se puede omitir, como se indica a continuacin:


int[] numbers = new int[] {1, 2, 3, 4, 5}; string[] names = new string[] {"Matt", "Joanne", "Robert"};

Tambin se puede omitir el operador new si se utiliza un inicializador como el siguiente:


int[] numbers = {1, 2, 3, 4, 5}; string[] names = {"Matt", "Joanne", "Robert"};

Matrices multidimensionales
int[,] numbers = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} }; string[,] siblings = new string[2, 2] { {"Mike","Amy"}, {"Mary","Albert"} };

El tamao de la matriz se puede omitir, como se indica a continuacin:


int[,] numbers = new int[,] { {1, 2}, {3, 4}, {5, 6} }; string[,] siblings = new string[,] { {"Mike","Amy"}, {"Mary","Albert"} };

Tambin se puede omitir el operador new si se utiliza un inicializador como el siguiente:


int[,] numbers = { {1, 2}, {3, 4}, {5, 6} }; string[,] siblings = { {"Mike", "Amy"}, {"Mary", "Albert"} };

Matriz escalonada (matriz de matrices) Las matrices escalonadas se pueden inicializar como en el siguiente ejemplo:
int[][] numbers = new int[2][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };

El tamao de la primera matriz se puede omitir, como se indica a continuacin:


int[][] numbers = new int[][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };

O bien
int[][] numbers = { new int[] {2,3,4}, new int[] {5,6,7,8,9} };

Observe que no existe sintaxis de inicializacin para los elementos de una matriz escalonada.

Acceso a miembros de matrices

El acceso a los miembros de una matriz es sencillo y similar al de los miembros de una matriz de C o C++. Por ejemplo, el siguiente cdigo crea una matriz denominada numbers y, a continuacin, asigna un 5 al quinto elemento de la matriz:
int[] numbers = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; numbers[4] = 5;

El siguiente cdigo declara una matriz multidimensional y asigna el valor 5 al miembro ubicado en [1, 1]:
int[,] numbers = { {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10} }; numbers[1, 1] = 5;

La siguiente es una declaracin de una matriz escalonada de una sola dimensin que contiene dos elementos. El primer elemento es una matriz de dos enteros, mientras que el segundo es una matriz de tres enteros:
int[][] numbers = new int[][] { new int[] {1, 2}, new int[] {3, 4, 5} };

La siguiente instruccin asigna 58 al primer elemento de la primera matriz y 667 al segundo elemento de la segunda matriz:
numbers[0][0] = 58; numbers[1][1] = 667;

Las matrices son objetos

En C#, las matrices son realmente objetos. System.Array es el tipo base abstracto de todos los tipos de matrices. Las propiedades y otros miembros de la clase System.Array se pueden utilizar cuando sea necesario. Un ejemplo de esto sera utilizar la propiedad Length para obtener la longitud de una matriz. El siguiente cdigo asigna la longitud de la matriz numbers, que es 5, a una variable denominada LengthOfNumbers:
int[] numbers = {1, 2, 3, 4, 5}; int LengthOfNumbers = numbers.Length;

La clase System.Array proporciona muchos otros mtodos y propiedades tiles, como mtodos para ordenar, buscar y copiar matrices.
Usar foreach con matrices

C# dispone de la instruccin foreach. Esta instruccin proporciona un modo simple y limpio de iterar en los elementos de una matriz. Por ejemplo, el siguiente cdigo crea una matriz denominada numbers y la recorre mediante la instruccin foreach:

int[] numbers = {4, 5, 6, 1, 2, 3, -2, -1, 0}; foreach (int i in numbers) { System.Console.WriteLine(i); }

Con matrices multidimensionales, se puede utilizar el mismo mtodo para recorrer los elementos, por ejemplo:
int[,] numbers = new int[3, 2] {{9, 99}, {3, 33}, {5, 55}}; foreach(int i in numbers) { Console.Write("{0} ", i); }

El resultado de este ejemplo es:


9 99 3 33 5 55

Sin embargo, con matrices multidimensionales, utilizar un bucle for anidado proporciona ms control sobre los elementos de la matriz.

Tutorial
Este tutorial incluye dos ejemplos. El primer ejemplo muestra cmo declarar y utilizar las propiedades de lectura y escritura. El segundo ejemplo ilustra las propiedades abstractas y muestra cmo reemplazar estas propiedades en subclases. Ejemplo 1 Este ejemplo muestra una clase Person con dos propiedades: Name (cadena) y Age (entero). Ambas propiedades son de lectura y escritura.
// person.cs using System; class Person { private string myName ="N/A"; private int myAge = 0; // Declare a Name property of type string: public string Name { get { return myName; } set { myName = value; }

} // Declare an Age property of type int: public int Age { get { return myAge; } set { myAge = value; } } public override string ToString() { return "Name = " + Name + ", Age = " + Age; } public static void Main() { Console.WriteLine("Simple Properties"); // Create a new Person object: Person person = new Person(); // Print out the name and the age associated with the person: Console.WriteLine("Person details - {0}", person); // Set some values on the person object: person.Name = "Joe"; person.Age = 99; Console.WriteLine("Person details - {0}", person); // Increment the Age property: person.Age += 1; Console.WriteLine("Person details - {0}", person); } }

Resultado
Simple Person Person Person Properties details - Name = N/A, Age = 0 details - Name = Joe, Age = 99 details - Name = Joe, Age = 100

Descripcin del cdigo


Observe la forma en que se declaran las propiedades; por ejemplo, considere la propiedad Name:
public string Name { get

{ return myName; } set { myName = value; } }

Los mtodos Set y Get de una propiedad estn contenidos dentro de la declaracin de propiedad. Se puede controlar si una propiedad es de lectura y escritura, de slo lectura o de slo escritura segn el mtodo, Get o Set, que se incluya.

Una vez declaradas las propiedades, se pueden utilizar como si fueran campos de la clase. Esto permite una sintaxis muy natural, tanto para obtener como para establecer el valor de una propiedad, como se muestra en las siguientes instrucciones:
person.Name = "Joe"; person.Age = 99;

Observe que, en un mtodo Set de una propiedad, se dispone de una variable especial value. Esta variable contiene el valor especificado por el usuario, por ejemplo:
myName = value;

Observe la sintaxis tan simple que se utiliza para incrementar la propiedad Age de un objeto Person:
person.Age += 1;

Si se utilizaron mtodos Set y Get independientes para modelar las propiedades, el cdigo equivalente tendra el siguiente aspecto:
person.SetAge(person.GetAge() + 1);

En el siguiente ejemplo, el mtodo ToString se reemplaza:


public override string ToString() { return "Name = " + Name + ", Age = " + Age; }

Observe que ToString no se utiliza explcitamente en el programa. Se invoca de forma predeterminada mediante las llamadas WriteLine. Ejemplo 2 En el ejemplo siguiente, se muestra cmo definir propiedades abstractas. Una declaracin de propiedad abstracta no proporciona una implementacin de los descriptores de acceso a la propiedad. El ejemplo muestra cmo reemplazar estas propiedades en subclases. Este ejemplo consta de tres archivos: En el Ejemplo Properties, estos archivos se compilan de una sola vez, pero en este tutorial, cada archivo se compila individualmente y se hace referencia al ensamblado resultante mediante la siguiente compilacin:

abstractshape.cs: la clase Shape que contiene una propiedad abstracta Area. shapes.cs: las subclases de la clase Shape. shapetest.cs: un programa de prueba que muestra en pantalla las reas de algunos objetos derivados de Shape.

Para compilar el ejemplo, utilice la lnea de comandos:


csc abstractshape.cs shapes.cs shapetest.cs

De esta forma, se crear el archivo ejecutable shapetest.exe. Archivo 1 - abstractshape.cs Este archivo declara la clase Shape que contiene la propiedad Area del tipo double
// abstractshape.cs // compile with: /target:library // csc /target:library abstractshape.cs using System; public abstract class Shape { private string myId; public Shape(string s) { Id = s; // calling the set accessor of the Id property } public string Id { get { return myId; } set { myId = value; } } // Area is a read-only property - only a get accessor is needed: public abstract double Area { get; } public override string ToString() { return Id + " Area = " + string.Format("{0:F2}",Area); } }

Descripcin del cdigo


Los modificadores de la propiedad se colocan en la propia declaracin de propiedad, por ejemplo:


public abstract double Area

Cuando se declara una propiedad abstracta (tal como Area en este ejemplo), simplemente se indica qu descriptores de acceso a la propiedad estn disponibles, pero no se implementan. En este ejemplo, slo se dispone de un descriptor de acceso Get, de modo que la propiedad es de slo lectura.

Archivo 2 - shapes.cs El siguiente cdigo muestra tres subclases de Shape y cmo reemplazan la propiedad Area para proporcionar sus propias implementaciones.
// shapes.cs // compile with: /target:library /reference:abstractshape.dll public class Square : Shape { private int mySide; public Square(int side, string id) : base(id) { mySide = side; } public override double Area { get { // Given the side, return the area of a square: return mySide * mySide; } } } public class Circle : Shape { private int myRadius; public Circle(int radius, string id) : base(id) { myRadius = radius; } public override double Area { get { // Given the radius, return the area of a circle: return myRadius * myRadius * System.Math.PI; } } }

public class Rectangle : Shape { private int myWidth; private int myHeight; public Rectangle(int width, int height, string id) : base(id) { myWidth = width; myHeight = height; } public override double Area { get { // Given the width and height, return the area of a rectangle: return myWidth * myHeight; } } }

Archivo 3 - shapetest.cs El siguiente cdigo muestra un programa de prueba que crea una serie de objetos derivados de Shape e imprime sus reas.
// shapetest.cs // compile with: /reference:abstractshape.dll;shapes.dll public class TestClass { public static void Main() { Shape[] shapes = { new Square(5, "Square #1"), new Circle(3, "Circle #1"), new Rectangle( 4, 5, "Rectangle #1") }; System.Console.WriteLine("Shapes Collection"); foreach(Shape s in shapes) { System.Console.WriteLine(s); } } }

Resultado
Shapes Collection Square #1 Area = 25.00 Circle #1 Area = 28.27 Rectangle #1 Area = 20.00

Interoperabilidad COM, parte 1: tutorial de clientes de C#


Visual Studio .NET 2003 Personas que lo han encontrado til: 0 de 1 - Valorar este tema

La interoperabilidad COM proporciona el acceso a componentes COM existentes sin necesidad de modificar el componente original. Cuando desee incorporar cdigo COM a una aplicacin administrada, importe los tipos COM correspondientes mediante una herramienta de interoperabilidad COM (TlbImp.exe) destinada a ese fin. Una vez importados, los tipos COM estn listos para usar. Asimismo, la interoperabilidad COM tambin permite a los programadores de COM obtener acceso a los objetos administrados igual de fcilmente que con otros objetos COM. La interoperabilidad COM proporciona una herramienta especializada (RegAsm.exe) que exporta los tipos administrados a una biblioteca de tipos y registra el componente administrado como un componente COM tradicional. En tiempo de ejecucin, Common Language Runtime realiza el clculo de referencias entre objetos COM y los objetos administrados, segn sea necesario. Este tutorial muestra cmo utilizar C# para interactuar con objetos COM. El Tutorial de "Interoperabilidad COM, parte2: servidor de C#" explica el uso de un servidor de C# con un cliente COM de C++. Para ver informacin general sobre ambos tutoriales, vea Tutoriales de interoperabilidad COM.

Archivos de ejemplo
Vea Interoperabilidad COM, parte 1: Ejemplo para descargar y generar los archivos de ejemplo que se utilizan en este tutorial.

Informacin adicional

Atributos de C# 17. Atributos Interoperabilidad COM avanzada System.Runtime.InteropServices (Espacio de nombres) Resumen de la conversin de una biblioteca de tipos en ensamblado Herramienta Type Library Importer (Tlbimp.exe) Herramienta MSIL Disassembler (Ildasm.exe) Herramienta Assembly Registration (Regasm.exe) Clculo de referencias para interoperabilidad Tutorial de "Interoperabilidad COM, parte 2: servidor de C#"

Tutorial

C# utiliza las herramientas de .NET Framework para implementar la interoperabilidad COM. C# admite las siguientes operaciones:

Crear objetos COM. Determinar si una interfaz COM es implementada por un objeto. Llamar a mtodos en interfaces COM. Implementar objetos e interfaces que puedan ser llamados por objetos COM.

.NET Framework controla las cuestiones de recuento de referencias con la interoperabilidad COM, por lo que no hay necesidad de llamar a (o implementar) AddRef y Release. Este tutorial trata los siguientes temas:

Crear un contenedor de clases COM Declarar una coclase COM Crear un objeto COM Declarar una interfaz COM Utilizar conversiones de tipo explcitas en lugar de QueryInterface Resumen de conceptos

Crear un contenedor de clases COM

Para que se pueda hacer referencia en el cdigo C# a objetos e interfaces COM, es necesario incluir una definicin de .NET Framework para las interfaces COM a la hora de generar dicho cdigo. La forma ms sencilla de hacerlo es utilizar TlbImp.exe (Type Library Importer), una herramienta de la lnea de comandos incluida en .NET Framework SDK. TlbImp convierte una biblioteca de tipos COM en metadatos de .NET Framework, creando as un contenedor administrado al que es posible llamar desde cualquier lenguaje administrado. Los metadatos de .NET Framework creados mediante TlbImp pueden incluirse en una generacin de cdigo C# con la opcin del compilador /R. Si utiliza el entorno de desarrollo de Visual Studio, slo es necesario agregar una referencia a la biblioteca de tipos COM y la conversin se har automticamente. TlbImp realiza las siguientes conversiones:

Las coclases COM se convierten en clases de C# con un constructor sin parmetros. Las estructuras COM se convierten en estructuras de C# con campos pblicos.

Una forma excelente de comprobar los resultados de la conversin que realiza TlbImp es ejecutar la herramienta de lnea de comandos Ildasm.exe (Microsoft Intermediate Language Disassembler), de .NET Framework SDK. Si bien TlbImp representa el mtodo preferente para convertir definiciones COM a C#, a veces no es posible usarla (por ejemplo, cuando no hay biblioteca de tipos para las definiciones COM, o si TlbImp no es capaz de controlar las definiciones de la biblioteca de tipos). En esos casos, la alternativa consiste en definir manualmente las definiciones COM en cdigo fuente de C# utilizando atributos de C#. Una vez creada la asignacin de cdigo

fuente C#, basta con compilar el cdigo fuente de C# para producir el contenedor administrado. Los principales atributos que es necesario comprender para realizar la asignacin COM son:

ComImport marca una clase como clase COM implementada externamente. Guid se utiliza para especificar un identificador nico universal (UUID) para una clase o interfaz. InterfaceType especifica si una interfaz se deriva de IUnknown o IDispatch. PreserveSig especifica si el valor devuelto nativo debe convertirse de un identificador HRESULT a una excepcin de.NET Framework.

Cada uno de estos atributos se muestra en el contexto de un ejemplo real en este tutorial.
Declarar una coclase COM

Las coclases COM se representan en C# como clases. Estas clases deben tener asociado el atributo ComImport. Las restricciones siguientes se aplican slo a estas clases:

La clase no se debe derivar de ninguna otra clase. La clase no debe implementar ninguna interfaz. La clase tambin debe tener un atributo Guid que establezca su identificador nico global (GUID).

El ejemplo siguiente declara una coclase en C#:


// // declare FilgraphManager as a COM coclass // [ComImport, Guid("E436EBB3-524F-11CE-9F53-0020AF0BA770")] class FilgraphManager { }

El compilador de C# agregar un constructor sin parmetros al que se puede llamar para crear una instancia de la coclase COM.
Crear un objeto COM

Las coclases COM se representan en C# como clases con un constructor sin parmetros. Crear una instancia de esta clase mediante el operador new es el equivalente en C# a llamar a CoCreateInstance. Sirvindose de la clase definida anteriormente, es sencillo crear una instancia de ella:
class MainClass { public static void Main() {

// // Create an instance of a COM coclass - calls // // CoCreateInstance(E436EBB3-524F-11CE-9F53-0020AF0BA770, // NULL, CLSCTX_ALL, // IID_IUnknown, &f) // // returns null on failure. // FilgraphManager f = new FilgraphManager(); } }

Declarar una interfaz COM

Las interfaces COM se representan en C# como interfaces con atributos ComImport y Guid. No puede incluir ninguna interfaz en su lista de interfaces base, y deben declarar las funciones miembro de interfaz en el orden en que aparecen los mtodos en la interfaz COM. Las interfaces COM declaradas en C# deben incluir declaraciones de todos los miembros de sus interfaces base, con excepcin de los miembros de IUnknown o IDispatch, ya que .NET Framework los agrega automticamente. Las interfaces COM que se derivan de IDispatch deben marcarse con el atributo InterfaceType. Al llamar a un mtodo de interfaz COM desde cdigo C#, Common Language Runtime debe realizar el clculo de referencias desde los parmetros y valores devueltos al objeto COM y viceversa. Por cada tipo de .NET Framework hay un tipo predeterminado que Common Language usar para calcular las referencias en una llamada COM. Por ejemplo, el clculo de referencias predeterminado para los valores de cadena de C# es al tipo nativo LPTSTR (puntero a un bfer de caracteres TCHAR). Se puede reemplazar el clculo de referencias predeterminado utilizando el atributo MarshalAs en la declaracin de C# de la interfaz COM. Una forma habitual en COM de devolver un resultado con xito o error es devolver un valor HRESULT y marcar un parmetro de salida como "retval" en MIDL, para el valor devuelto real del mtodo. En C# (y en .NET Framework), la manera estndar de indicar que se ha producido un error es iniciar una excepcin. De forma predeterminada, .NET Framework proporciona una asignacin automtica entre los dos estilos de control de excepciones para los mtodos de interfaces COM invocados por .NET Framework.

El valor devuelto cambia a la firma del parmetro marcado como retval (void si el mtodo no tiene ningn parmetro marcado como retval). El parmetro marcado como retval aparece a la izquierda de la lista de argumentos del mtodo.

Cualquier valor devuelto diferente del xito en la operacin har que se inicie una excepcin System.COMException. Este ejemplo muestra una interfaz COM declarada en MIDL y la misma interfaz declarada en C# (observe que los mtodos utilizan el modelo de control de excepciones COM). Esta es la versin original MIDL de la interfaz:
[ odl, uuid(56A868B1-0AD4-11CE-B03A-0020AF0BA770), helpstring("IMediaControl interface"), dual, oleautomation ] interface IMediaControl : IDispatch { [id(0x60020000)] HRESULT Run(); [id(0x60020001)] HRESULT Pause(); [id(0x60020002)] HRESULT Stop(); [id(0x60020003)] HRESULT GetState( [in] long msTimeout, [out] long* pfs); [id(0x60020004)] HRESULT RenderFile([in] BSTR strFilename); [id(0x60020005)] HRESULT AddSourceFilter( [in] BSTR strFilename, [out] IDispatch** ppUnk); [id(0x60020006), propget] HRESULT FilterCollection([out, retval] IDispatch** ppUnk); [id(0x60020007), propget] HRESULT RegFilterCollection([out, retval] IDispatch** ppUnk); [id(0x60020008)] HRESULT StopWhenReady(); };

ste es el equivalente en C# de la interfaz:


using System.Runtime.InteropServices; // Declare IMediaControl as a COM interface which // derives from the IDispatch interface. [Guid("56A868B1-0AD4-11CE-B03A-0020AF0BA770"), InterfaceType(ComInterfaceType.InterfaceIsDual)]

interface IMediaControl // cannot list any base interfaces here { // Note that the members of IUnknown and Interface are NOT // listed here // void Run(); void Pause(); void Stop(); void GetState( [In] int msTimeout, [Out] out int pfs); void RenderFile( [In, MarshalAs(UnmanagedType.BStr)] string strFilename); void AddSourceFilter( [In, MarshalAs(UnmanagedType.BStr)] string strFilename, [Out, MarshalAs(UnmanagedType.Interface)] out object ppUnk); [return : MarshalAs(UnmanagedType.Interface)] object FilterCollection(); [return : MarshalAs(UnmanagedType.Interface)] object RegFilterCollection(); void StopWhenReady(); }

Observe que la interfaz C# ha asignado los casos de control de error. Si el mtodo COM devuelve un error, se iniciar una excepcin en la parte de C#. Para impedir la conversin de HRESULT a excepciones COMException, asocie el atributo PreserveSig(true) al mtodo en la declaracin de C#. Para obtener informacin detallada, vea PreserveSigAttribute (Clase).
Utilizar conversiones de tipo explcitas en lugar de QueryInterface

Una coclase de C# no resulta de gran utilidad a menos que se disponga de acceso a una interfaz que la implemente. En C++ lo habitual es recorrer las interfaces de un objeto utilizando el mtodo QueryInterface en la interfaz IUnknown. En C# podemos hacer lo mismo realizando una conversin explcita del objeto COM a la interfaz deseada. Si la conversin explcita no funciona, se inicia una excepcin InvalidCastException:
// Create an instance of a COM coclass: FilgraphManager graphManager = new FilgraphManager(); // See if it supports the IMediaControl COM interface. // Note that this will throw a System.InvalidCastException if // the cast fails. This is equivalent to QueryInterface for // COM objects: IMediaControl mc = (IMediaControl) graphManager;

// Now you call a method on a COM interface: mc.Run();

Resumen de conceptos

A continuacin se muestra un ejemplo completo que crea un visor de archivos AVI utilizando C#. El programa crea una instancia de una coclase COM, la convierte explcitamente a una interfaz COM y despus llama a los mtodos de la interfaz COM. Los ejemplos de esta seccin representan dos modelos:

Ejemplo 1 Se utiliza TlbImp para crear la clase de .NET Framework. Ejemplo 2 Se crea cdigo de C# que realiza manualmente la asignacin COM.

Ejemplo 1: utilizar TlbImp Este ejemplo muestra cmo crear un visor AVI con TlbImp. El programa lee un nombre de archivo AVI en la lnea de comandos, crea una instancia del objeto COM Quartz y, a continuacin, usa los mtodos RenderFile y Run para mostrar el archivo AVI. Estos son los pasos para generar el programa:

Ejecute TlbImp sobre la biblioteca de tipos. El Reproductor multimedia utilizado en este ejemplo se encuentra en Quartz.DLL, que debe hallarse en el directorio del sistema de Windows. Utilice el siguiente comando para crear la DLL de .NET Framework:
tlbimp c:\winnt\system32\quartz.dll /out:QuartzTypeLib.dll

Observe que la DLL resultante debe tener el nombre QuartzTypeLib, de manera que .NET Framework pueda cargar los tipos contenedores correctamente al ejecutarse.

Se puede utilizar la herramienta Ildasm para examinar la DLL resultante. Por ejemplo, para mostrar el contenido del archivo QuartzTypeLib.dll, utilice el comando siguiente:
Ildasm QuartzTypeLib.dll

Genere el programa con la opcin del compilador de C# /R para incluir el archivo QuartzTypeLib.dll.

A continuacin puede usar el programa para mostrar un archivo de pelcula (puede intentarlo con Clock.avi, incluido en el directorio Windows).
// interop1.cs // compile with: /R:QuartzTypeLib.dll using System; class MainClass { /************************************************************ Abstract: This method collects the file name of an AVI to show then creates an instance of the Quartz COM object. To show the AVI, the program calls RenderFile and Run on

IMediaControl. Quartz uses its own thread and window to display the AVI.The main thread blocks on a ReadLine until the user presses ENTER. Input Parameters: the location of the AVI file it is going to display Returns: void **************************************************************/ public static void Main(string[] args) { // Check to see if the user passed in a filename if (args.Length != 1) { DisplayUsage(); return; } if (args[0] == "/?") { DisplayUsage(); return; } string filename = args[0]; // Check to see if the file exists if (!System.IO.File.Exists(filename)) { Console.WriteLine("File " + filename + " not found."); DisplayUsage(); return; } // Create instance of Quartz // (Calls CoCreateInstance(E436EBB3-524F-11CE-9F530020AF0BA770, // NULL, CLSCTX_ALL, IID_IUnknown, &graphManager).): try { QuartzTypeLib.FilgraphManager graphManager = new QuartzTypeLib.FilgraphManager(); // QueryInterface for the IMediaControl interface: QuartzTypeLib.IMediaControl mc = (QuartzTypeLib.IMediaControl)graphManager; // Call some methods on a COM interface // Pass in file to RenderFile method on COM object. mc.RenderFile(filename); // Show file. mc.Run(); } catch(Exception ex) { Console.WriteLine("Unexpected COM exception: " + ex.Message);

} // Wait for completion. Console.WriteLine("Press Enter to continue."); Console.ReadLine(); } private static void DisplayUsage() { // User did not provide enough parameters. // Display usage: Console.WriteLine("VideoPlayer: Plays AVI files."); Console.WriteLine("Usage: VIDEOPLAYER.EXE filename"); Console.WriteLine("where filename is the full path and"); Console.WriteLine("file name of the AVI to display."); } }

Ejecucin de ejemplo Para mostrar la pelcula de ejemplo, Clock.avi, utilice el siguiente comando:
interop1 %windir%\clock.avi

Con ello ver la pelcula en su pantalla al presionar ENTRAR. Ejemplo 2: el modelo de cdigo de C# Este ejemplo usa el mismo mtodo Main que el Ejemplo 1, pero en lugar de ejecutar TlbImp, asigna el objeto COM Reproductor multimedia mediante C#:
// interop2.cs using System; using System.Runtime.InteropServices; namespace QuartzTypeLib { // Declare IMediaControl as a COM interface which // derives from IDispatch interface: [Guid("56A868B1-0AD4-11CE-B03A-0020AF0BA770"), InterfaceType(ComInterfaceType.InterfaceIsDual)] interface IMediaControl // Cannot list any base interfaces here { // Note that IUnknown Interface members are NOT listed here: void Run(); void Pause(); void Stop(); void GetState( [In] int msTimeout, [Out] out int pfs); void RenderFile(

[In, MarshalAs(UnmanagedType.BStr)] string strFilename); void AddSourceFilter( [In, MarshalAs(UnmanagedType.BStr)] string strFilename, [Out, MarshalAs(UnmanagedType.Interface)] out object ppUnk); [return: MarshalAs(UnmanagedType.Interface)] object FilterCollection(); [return: MarshalAs(UnmanagedType.Interface)] object RegFilterCollection(); void StopWhenReady(); } // Declare FilgraphManager as a COM coclass: [ComImport, Guid("E436EBB3-524F-11CE-9F53-0020AF0BA770")] class FilgraphManager // Cannot have a base class or // interface list here. { // Cannot have any members here // NOTE that the C# compiler will add a default constructor // for you (no parameters). } } class MainClass { /********************************************************** Abstract: This method collects the file name of an AVI to show then creates an instance of the Quartz COM object. To show the AVI, the program calls RenderFile and Run on IMediaControl. Quartz uses its own thread and window to display the AVI.The main thread blocks on a ReadLine until the user presses ENTER. Input Parameters: the location of the AVI file it is going to display Returns: void *************************************************************/ public static void Main(string[] args) { // Check to see if the user passed in a filename: if (args.Length != 1) { DisplayUsage(); return; } if (args[0] == "/?") { DisplayUsage(); return; } String filename = args[0];

// Check to see if the file exists if (!System.IO.File.Exists(filename)) { Console.WriteLine("File " + filename + " not found."); DisplayUsage(); return; } // Create instance of Quartz // (Calls CoCreateInstance(E436EBB3-524F-11CE-9F530020AF0BA770, // NULL, CLSCTX_ALL, IID_IUnknown, // &graphManager).): try { QuartzTypeLib.FilgraphManager graphManager = new QuartzTypeLib.FilgraphManager(); // QueryInterface for the IMediaControl interface: QuartzTypeLib.IMediaControl mc = (QuartzTypeLib.IMediaControl)graphManager; // Call some methods on a COM interface. // Pass in file to RenderFile method on COM object. mc.RenderFile(filename); // Show file. mc.Run(); } catch(Exception ex) { Console.WriteLine("Unexpected COM exception: " + ex.Message); } // Wait for completion. Console.WriteLine("Press Enter to continue."); Console.ReadLine(); } private static void DisplayUsage() { // User did not provide enough parameters. // Display usage. Console.WriteLine("VideoPlayer: Plays AVI files."); Console.WriteLine("Usage: VIDEOPLAYER.EXE filename"); Console.WriteLine("where filename is the full path and"); Console.WriteLine("file name of the AVI to display."); } }

Ejecucin de ejemplo Para mostrar la pelcula de ejemplo, Clock.avi, utilice el siguiente comando:
interop2 %windir%\clock.avi

Con ello ver la pelcula en su pantalla al presionar ENTRAR.

Interoperabilidad COM, parte 2: tutorial de servidor de C#


Visual Studio .NET 2003 Este tema an no ha recibido ninguna valoracin - Valorar este tema

La interoperabilidad COM permite a los programadores de COM obtener acceso al cdigo administrado igual de fcilmente que con otros objetos COM. Este tutorial muestra el uso de un servidor C# con un cliente COM de C++. Tambin explica las actividades siguientes:

Cmo crear el servidor de C# Cmo crear el cliente COM

El tutorial tambin trata brevemente el clculo de referencias aplicado automticamente entre los componentes administrados y no administrados. Interoperabilidad COM, parte 1: tutorial de clientes de C# muestra los fundamentos del uso de C# para interactuar con objetos COM y es un requisito previo para poder seguir este tutorial. Para ver informacin general sobre ambos tutoriales, vea Tutoriales de interoperabilidad COM.

Archivos de ejemplo
Vea Interoperabilidad COM, parte 2: Ejemplo para descargar y generar los archivos de ejemplo que se utilizan en este tutorial.

Informacin adicional

Atributos de C# 17. Atributos Interoperabilidad COM avanzada System.Runtime.InteropServices (Espacio de nombres) Resumen de la conversin de una biblioteca de tipos en ensamblado Herramienta Assembly Registration (Regasm.exe) Herramienta Type Library Importer (Tlbimp.exe) Clculo de referencias para interoperabilidad Tutorial de "Interoperabilidad COM, parte 1: cliente de C#"

Tutorial
Este tutorial muestra los siguientes pasos para la creacin del servidor de C#:

Cmo utilizar el atributo Guid en interfaces y clases para exponerlas como objetos COM, y cmo generar un identificador nico global (GUID) para el atributo Guid. Cmo utilizar RegAsm para registrar un programa de .NET Framework para su uso por clientes COM, y cmo crear una biblioteca de tipos (archivo .tlb) desde un programa de .NET Framework.

El tutorial tambin ensea los pasos siguientes para crear el cliente COM:

Cmo exportar servidores administrados y cmo utilizarlos para crear objetos COM. Cmo importar el archivo .tlb, generado por RegAsm, en el cliente COM y cmo usar CoCreateInstance para crear una instancia de una coclase de .NET Framework. Nota Para crear un identificador GUID de interfaces y coclases que vaya a exportar a clientes COM, utilice la herramienta Guidgen.exe, que se incluye en Visual Studio. Guidgen permite elegir el formato que tendr el identificador GUID para que no sea necesario volver a escribirlo. Para obtener ms informacin sobre Guidgen, vea el artculo de Knowledge Base Q168318 "XADM: Guidgen.exe Available Only for Intel Platforms". Los artculos de Knowledge Base estn disponibles en la MSDN Library y en el Web, en http://www.microsoft.com/spanish/soporte/.

Ejemplo Este ejemplo consta de dos archivos:


Un archivo de C#, CSharpServer.C#, que crea el archivo CSharpServer.dll. El archivo .dll se usa para crear CSharpServer.tlb. Un archivo de C++, COMClient.cpp, que crea el cliente ejecutable, COMClient.exe.

Archivo 1: CSharpServer.cs
// CSharpServer.cs // compile with: /target:library // post-build command: regasm CSharpServer.dll /tlb:CSharpServer.tlb using System; using System.Runtime.InteropServices; namespace CSharpServer { // Since the .NET Framework interface and coclass have to behave as // COM objects, we have to give them guids. [Guid("DBE0E8C4-1C61-41f3-B6A4-4E2F353D3D05")] public interface IManagedInterface { int PrintHi(string name); } [Guid("C6659361-1625-4746-931C-36014B146679")] public class InterfaceImplementation : IManagedInterface { public int PrintHi(string name)

{ Console.WriteLine("Hello, {0}!", name); return 33; } } }

Archivo 2: COMClient.cpp
// COMClient.cpp // Build with "cl COMClient.cpp" // arguments: friend #include <windows.h> #include <stdio.h> #pragma warning (disable: 4278) // To use managed-code servers like the C# server, // we have to import the common language runtime: #import <mscorlib.tlb> raw_interfaces_only // For simplicity, we ignore the server namespace and use named guids: #if defined (USINGPROJECTSYSTEM) #import "..\RegisterCSharpServerAndExportTLB\CSharpServer.tlb" no_namespace named_guids #else // Compiling from the command line, all files in the same directory #import "CSharpServer.tlb" no_namespace named_guids #endif int main(int argc, char* argv[]) { IManagedInterface *cpi = NULL; int retval = 1; // Initialize COM and create an instance of the InterfaceImplementation class: CoInitialize(NULL); HRESULT hr = CoCreateInstance(CLSID_InterfaceImplementation, NULL, CLSCTX_INPROC_SERVER, IID_IManagedInterface, reinterpret_cast<void**>(&cpi)); if (FAILED(hr)) { printf("Couldn't create the instance!... 0x%x\n", hr); } else { if (argc > 1) { printf("Calling function.\n"); fflush(stdout); // The variable cpi now holds an interface pointer // to the managed interface. // If you are on an OS that uses ASCII characters at the // command prompt, notice that the ASCII characters are

// automatically marshaled to Unicode for the C# code. if (cpi->PrintHi(argv[1]) == 33) retval = 0; printf("Returned from function.\n"); } else printf ("Usage: cpi->Release(); cpi = NULL; } // Be a good citizen and clean up COM: CoUninitialize(); return retval; } COMClient <name>\n");

Resultado El cliente ejecutable puede invocarse con la lnea de comandos: COMClient <name>, donde <name> es cualquier cadena que desee utilizar, como por ejemplo COMClient friend.
Calling function. Hello, friend! Returned from function.

En el ejemplo proyecto IDE, establezca la propiedad Argumentos de la lnea de comandos a la cadena deseada (por ejemplo, "amigo") en las pginas Propiedades del proyecto.

Вам также может понравиться