Wenn ich so ein Scenario baue, dann bekommt das nicht generische Interface für gewöhnlich die selbe Property vom Typ object und wird explizit implementiert.
Wenn das in deinem Fall nicht so ist und Du das auch nicht ändern kannst, dann wirst Du vermutlich nicht um Reflection herum kommen, da Du ja auch keinen Einfluss auf die Implementierung des Interfaces hast.
Bei Reflection brauchst Du dich aber nicht um den generischen Typ kümmern, da der schon fest steht und sich der Typ dann wie jeder andere Typ verhält.
Es reicht also, wenn Du die Message nach dem Message-Typ fragst, den dann nach einer Property mit dem Namen DataItem und darauf dann GetValue aufrufst.
object dataItem = message.GetType().GetProperty("DataItem").GetValue(message);
Noch ein bisschen Fehlerbehandlung drum herum, wenn z.B. die Property DataItem nicht existiert, dass Du das irgendwie behandeln kannst.
@LaTino:
Streng genommen ist ein GenericMessage<T> ein normaler Typ, zumindest behandelt .NET das als normalen Typ. An den kommst Du mit typeof(GenericMessage<>)
Du kannst auch alle Reflection-Operationen damit machen, aber nur so lange Du nicht "aktiv" mit den Membern arbeiten - z.B. Ausführen - musst.
Damit kannst Du so lange arbeiten, bis der konkrete generiche Parameter notwendig ist. Ausführen von Methoden geht also nicht, Definitionen abfragen aber schon.
Interessanterweise ist selbst das T ein normaler und eindeutiger Typ. Der beinhaltet das, was auch object kann plus das, was die Constraints vorschreiben.
An das T kommst Du, wenn Du über den generischen nicht konkreten Typ mit GetGenericArguments nach den Generischen Parametern fragst.
Du kannst auch vollständig damit arbeiten, wenn Du eine Instanz nimmst, die die Constraints erfüllt.
Das nur am Rande