Frage


Die Frage

Meine Frage lautet: Ist nativ C # unterstützen späte Bindung IDispatch

?

Pretend ich versuche Büro zu automatisieren, während mit kompatibel ist, was auch immer Version der Kunde installiert hat.

In der .NET-Welt, wenn Sie mit Office 2000 entwickelt installiert, jedem Entwickler und jeder Kunde, ab jetzt bis zum Ende der Zeit, erforderlich ist, Office 2000 haben.

In der Welt vor .NET verwenden wir COM , um Office-Anwendungen zu sprechen.

Zum Beispiel:

1) Verwenden Sie die Version unabhängige ProgID

"Excel.Application"

, die aufgelöst werden:

clsid = {00024500-0000-0000-C000-000000000046}

und dann COM verwenden, bitten wir um eine dieser Klassen in ein Objekt instanziert werden:

IUnknown unk;
CoCreateInstance(
    clsid, 
    null,
    CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
    IUnknown, 
    out unk);

Und jetzt sind wir aus dem Rennen - in der Lage Excel zu verwenden, aus dem Innern meiner Anwendung. Natürlich, wenn wirklich Sie das Objekt verwenden möchten, müssen Sie eine Möglichkeit zu nennen Methoden aufrufen.

Wir könnte erhalten ahold der verschiedenen Schnittstelle Erklärungen, in unsere Sprache übersetzt. Diese Technik ist gut, weil wir bekommen

  • frühe Bindung
  • Code-insight
  • kompilieren Typ Syntaxprüfung

und einige Beispiel-Code könnte sein:

Application xl = (IExcelApplication)unk;
ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid);
Worksheet worksheet = workbook.ActiveSheet;

Aber es gibt eine Kehrseite Schnittstellen verwenden: wir ahold der verschiedenen Schnittstellendeklarationen bekommen müssen, transated in unserer Sprache. Und wir sind methodenbasierte Anrufungen stecken verwenden, mit allen Parametern angeben, z.

ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid);
xl.Worksheets.Add(before, after, count, type, lcid);

Das bewiesen hat, in der realen Welt, solche Nachteile, die wir gerne verzichten würden:

  • frühe Bindung
  • Code-insight
  • kompilieren Zeit Syntaxprüfung

und verwenden Sie stattdessen IDispatch die späte Bindung:

Variant xl = (IDispatch)unk;
Variant newWorksheet = xl.Worksheets.Add();

Da Excel-Automatisierung für VB Script entwickelt wurde, kann eine Menge Parameter weggelassen werden, auch wenn es keine Überlastung ohne sie.

Hinweis: Verwechseln Sie nicht mein Beispiel von Excel mit ein Grund, warum ich will IDispatch verwenden. Nicht jedes COM-Objekt ist Excel. Einige COM-Objekte haben keine Unterstützung anderer Weise als über IDispatch.

War es hilfreich?

Lösung

Sie können, relativly, verwenden Sie die späte Bindung IDispatch in C # zu binden.

http://support.microsoft.com/kb/302902

Hier ist ein Beispiel für Excel. Auf diese Weise brauchen Sie nicht eine unnötige dependancy auf Microsofts bloaty PIA hinzuzufügen:

//Create XL
Object xl = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));

//Get the workbooks collection.
//   books = xl.Workbooks;
Object books = xl.GetType().InvokeMember( "Workbooks", 
      BindingFlags.GetProperty, null, xl, null);

//Add a new workbook.
//   book = books.Add();
Objet book = books.GetType().InvokeMember( "Add", 
      BindingFlags.InvokeMethod, null, books, null );

//Get the worksheets collection.
//   sheets = book.Worksheets;
Object sheets = book.GetType().InvokeMember( "Worksheets",
      BindingFlags.GetProperty, null, book, null );

Object[] parameters;

//Get the first worksheet.
//   sheet = sheets.Item[1]
parameters = new Object[1];
parameters[0] = 1;
Object sheet = sheets.GetType().InvokeMember( "Item", 
      BindingFlags.GetProperty, null, sheets, parameters );

//Get a range object that contains cell A1.
//   range = sheet.Range["A1];
parameters = new Object[2];
parameters[0] = "A1";
parameters[1] = Missing.Value;
Object range = sheet.GetType().InvokeMember( "Range",
      BindingFlags.GetProperty, null, sheet, parameters );

//Write "Hello, World!" in cell A1.
//   range.Value = "Hello, World!";
parameters = new Object[1];
parameters[0] = "Hello, World!";
objRange_Late.GetType().InvokeMember( "Value", BindingFlags.SetProperty, 
      null, range, parameters );

//Return control of Excel to the user.
//   xl.Visible = true;
//   xl.UserControl = true;
parameters = new Object[1];
parameters[0] = true;
xl.GetType().InvokeMember( "Visible", BindingFlags.SetProperty,
      null, xl, Parameters );
xl.GetType().InvokeMember( "UserControl", BindingFlags.SetProperty,
      null, xl, Parameters );

Andere Tipps

Du musst warten, C # 4.0 zu kommen, um die späte Bindung zu bekommen, dass Sie suchen. Jedes Mal, wenn ich brauche Interop-Fähigkeiten ich VB.Net-Modus zurückschalten, damit ich die Vorteile der COM-Funktionen übernehmen kann, die C # zu fehlt scheinen.

Die einfache Methode, die ich benutze, ist eine Klasse in VB.Net zu schaffen, die die IDispatch Arbeit tut und dann die Methoden ausgesetzt wird, die ich als Methoden meiner Wrapper verwenden möchten, und dann kann ich sie nach Belieben von meinem C # Code aufrufen. Nicht die eleganteste Lösung, aber es hat mich aus der Patsche oder zwei in den letzten paar Monaten bekommen.

C # 4 der dynamic Schlüsselwort unterstützt IDispatch und die späte Bindung. Sie können Sam Ng dynamische Serie für weitere Informationen lesen

Oh, und C # 4 ist nur als CTP heute verfügbar. Sie werden entweder warten müssen, für Visual Studio vNext oder die Beta verwenden (die auf einem Windows Server 2008 Virtual PC läuft), die verwendet werden.

wahrscheinlich kann man mit vielen schönen Code in C # 2.0 / 3.0 weg, wenn Sie die Zeit nehmen, eine Schnittstelle zu schreiben mit den Methoden und Eigenschaften, die Sie von dem Objekt wollen und einige Attribute hinzufügen (i aus dem Speicher zu schreiben, so Details nicht richtig sein können, aber ich schwöre, es ist für mich gearbeitet ...)

    using System.Runtime.Interopservices;

    [Guid("00024500-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    interface IExcel
    {
      // sample property
      string Name{get;}
      // more properties
    }

    // and somewhere else
    void main()
    {
      Object xl = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
      IExcel excel = (IExcel)xl;
      string name = xl.name
    }

Wie bereits erwähnt, wird der Code nicht aus der Box arbeitet, ist es ein Hinweis, was in Msdn zu graben.

Wie bereits gesagt wurde - c # 4 des "dynamischen" keyword Felsen mit. Hier ist ein einfaches Beispiel - es ist so viel mehr als succint mit „InvokeMethod“

dynamic xl = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
dynamic books = xl.Workbooks;
dynamic book = books.Add();

Console.WriteLine(books.Count);     //Writes 1

foreach (dynamic b in books)        
{
Console.WriteLine(b.Name);      //Writes "Book1"
}

Hey Dude, ich habe 2 codeplex Projekte, die derzeit dieses Problem zu lösen.

die erste ist LateBindingApi.Excel http://excel.codeplex.com kartiert latebinded Aufruf der bekannten Objektmodell aufzurufen. dies war ein Testprojekt für das folgende Projekt.

das zweite ist ein Codegenerator http://latebindingapi.codeplex.com Das Tool erstellt c # -Projekte von COM Typ-Bibliotheken. die generierten Projekte enthält Objekte Mapper mit latebind den COM-Server zugreifen. Der Höhepunkt ist das Werkzeug COM Typ libs in verschiedenen Versionen zu einem einzigen Projekt (zB Excel 9,10,11) und markierte alle Einheiten, mit einem selbstdefinierten SupportByLibrary Attribute umwandelt. Ich habe alle Office-Anwendungen in Version jetzt 9,10,11,12,14 mit diesem diesem Tool analysiert und eine c # Lösung, die verfügbaren erzeugen, wie getestet Beta mit Beispielcode auf der Hauptseite.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top