Späte Bindung bei C# am Beispiel Word
Frank Dzaebel, erstellt am: 14.03.2005, zuletzt geändert:  25.1.2006
Kategorie: Latebinding, .NET-Version: 1.1

Versions-unabhängige Programmierung in Office
Unschön ist bei normaler C#-Programmierung, dass bei Befehlen wie Documents.Open(...) sehr viele Parameter als Missing.Value angegeben werden müssen. Das muss nicht sein. Man kann sich einen Wrapper bauen, der auf Basis des BindingFlags.OptionalParamBinding alle Methoden generisch mit den nur notwendigen Parametern aufruft. Auch ist man so geschützt vor dem Umstand, die Methoden in den unterschiedlichen Office-Versionen mit anderen Signaturen aufrufen zu müssen.

Links zum Office-Latebinding unter C#:
- Bindung von Office-Automatisierungsservern mit Visual C# .NET herstellen
- Verwenden der Automatisierung zum Abrufen und Festlegen von Office-Dokumenteigenschaften mit Visual C# .NET

object WordApp = null;
object WordDoc = null;
Type   WordType= null;
int    Version = 0   ;
private void button1_Click(object sender, EventArgs e)
{
  try
  {
    WordType = Type.GetTypeFromProgID ("Word.Application");
    if (WordType == null) 
    { MessageBox.Show("MS-Word ist nicht installiert."); return;}
    WordApp = Activator.CreateInstance(WordType);
    string Build = (string)WordType.InvokeMember("Build", 
      BindingFlags.GetProperty, null, WordApp, null);
    Version = int.Parse(Build.Split('.')[0]);
    WordType.InvokeMember("Visible", BindingFlags.SetProperty,
      null, WordApp, new Object[1] {true} );

    // nur ein Beispiel für einen spät gebundenen EnumWert 
    object wdFFHTML = GetEnumValue("WdSaveFormat", "wdFormatFilteredHTML");
	
    WordDoc = WordApp.GetType().InvokeMember("Documents", 
      BindingFlags.GetProperty, null, WordApp, null );
    // WordDoc.GetType().InvokeMember("Add", 
    // BindingFlags.InvokeMethod, null, WordDoc, null );
  }
  catch(TypeLoadException ex)
  { 
    MessageBox.Show("Fehler : " + ex.Message); 
  }
  this.BringToFront();
}

private void Form1_Closing(object sender, CancelEventArgs e)
{
  if (WordApp  == null || WordType == null) return;
  try
  { // Word kann vom User geschlossen sein.
    WordType.InvokeMember("Quit", 
      BindingFlags.InvokeMethod, null, WordApp, null );
    Marshal.ReleaseComObject(WordApp);
  }
  catch {}
}

private object GetEnumValue(string enumName, string enumValName)
{
  string aBase = WordType.Assembly.FullName.Split(',')[0];
  Type t = WordType.Assembly.GetType(aBase + "." + enumName);
  return t.GetField(enumValName).GetValue(WordType);
}

private void btnOpenDoc_Click(object sender, EventArgs e)
{
  if (WordApp == null) return; 
  object FilePath = Path.Combine(Path.GetTempPath(),"Example.doc");
  object o=Missing.Value; 
  try
  {
    object[] parameters = new object[1]{FilePath}; 
    object Doc = WordDoc.GetType().InvokeMember("Open", 
      BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, 
      null, WordDoc, parameters);
  }
  catch (Exception exp)
  {
    if (exp.InnerException != null) 
      MessageBox.Show(exp.InnerException.Message);
    else MessageBox.Show(exp.Message);
  }
}