Extensions

Deutschsprachiges X#-Forum – German language forum

Moderator: wriedmann

Post Reply
lagraf
Posts: 419
Joined: Thu Jan 18, 2018 9:03 am

Extensions

Post by lagraf »

In VO habe ich bei den internen Klassen öfter Methoden hinzugefügt, z.B:

Code: Select all

METHOD PostFocus() CLASS Control
    PostMessage( GetParent(SELF:Handle()) , WM_NextDlgCtl , DWORD( _CAST , SELF:Handle() ) , 1L )
    IF IsInstanceOf(SELF,#SingleLineEdit)
        PostMessage(SELF:Handle(), EM_SETSEL, 0, LONG(_CAST,SLen(RTrim(SELF:TextValue))))
        PostMessage(SELF:Handle(), EM_SCROLLCARET, 0, 0L )
    ELSEIF IsInstanceOf(SELF,#MultiLineEdit)
        PostMessage(SELF:Handle(), EM_SETSEL, 0, 0L )
        PostMessage(SELF:Handle(), EM_SCROLLCARET, 0, 0L )
    ENDIF
    RETURN NIL
In X# geht das ja nicht mehr, daher habe ich es mit Extensions versucht, damit ich die SLEs nicht von einer anderen Klasse ableiten muss:

Code: Select all

CLASS EditExtensions
METHOD PostFocus() 
    PostMessage( GetParent(SELF:Handle()) , WM_NextDlgCtl , DWORD( _CAST , SELF:Handle() ) , 1L )
    IF IsInstanceOf(SELF,#SingleLineEdit)
        PostMessage(SELF:Handle(), EM_SETSEL, 0, LONG(_CAST,SLen(RTrim(SELF:TextValue))))
        PostMessage(SELF:Handle(), EM_SCROLLCARET, 0, 0L )
    ELSEIF IsInstanceOf(SELF,#MultiLineEdit)
        PostMessage(SELF:Handle(), EM_SETSEL, 0, 0L )
        PostMessage(SELF:Handle(), EM_SCROLLCARET, 0, 0L )
    ENDIF
    RETURN NIL
END CLASS
Allerdings mag der Compiler den Zugriff auf SELF:Handle() und SELF:TextValue nicht. Kann man das lösen, ohne eine eigene Klasse MyEdit darüberzulegen und alle SLEs neu abzuleiten?
User avatar
wriedmann
Posts: 3649
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Extensions

Post by wriedmann »

Hallo Franz,
extension methods schreibt man anders:

Code: Select all

static method PostFocus( self oSLE as SingleLineEdit ) as void
dann kannst Du innerhalb der Methode mit

Code: Select all

PostMessage( oSLE:Handle() )
auf das SLE-Objekt zugreifen.
Aber Achtung: weil die Extension-Methode von außen an die Klasse drangeflanscht wird, hat sie keinen Zugriff auf Protects und sonstige Klassen-Interna.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
lagraf
Posts: 419
Joined: Thu Jan 18, 2018 9:03 am

Extensions

Post by lagraf »

Hallo Wolfgang,
dann sind die Extensions eine Art primitive Vererbung, wo den Methoden als erster Parameter das Mutterobjekt mitgegeben wird. Geht das auch mit Access und Assign?
Franz
User avatar
wriedmann
Posts: 3649
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Extensions

Post by wriedmann »

Hallo Franz,
extension methods sind im Prinzip von außen drangeflanschte Methoden, weil eine Klasse für sich selber immer abgeschlossen ist. Sie kann zwar auf mehrere Quellcode-Dateien aufgeteilt werden, aber immer nur in einer Assembly definiert werden.
Das hat damit zu tun, dass sie anderes als in VO komplett zur Compile-Zeit definiert wird (in VO wird die Liste der Methoden einer Klasse beim Laden der Applikation/DLL erstellt).
Für Access/Assign geht das leider nicht - wäre auch nicht sehr sinnvoll, da der Zugriff auf Klassen-Interna nicht möglich ist (da von außen drangehängt).
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
pemo18
Posts: 72
Joined: Fri Apr 27, 2018 10:38 am
Location: Germany

Extensions

Post by pemo18 »

Hallo Wolfgang,

Gut, dass Du mal so nebenbei die Schreibweise erwähnst, die ich in der X#-Hilfe nicht gefunden habe.

Ich habe vor kurzem eine Methode gebraucht, die aus einer generischen Liste eine DataTable macht. Dafür sind Extension Methods sehr praktisch.

Methode anbei.

Viele Grüße,
Peter

Class DataTableHelper

Static Method Convert2DataTable<T>(Self List as List<T>) As DataTable
Local ta := DataTable{} As DataTable
Local itemType := typeof(T) As Type
Local properties := TypeDescriptor.GetProperties(itemType) As PropertyDescriptorCollection
try
foreach propDesc As PropertyDescriptor in properties
ta:Columns:Add(DataColumn{propDesc:Name, propDesc:PropertyType})
next
foreach item As T in List
Local row := ta:NewRow() As DataRow
foreach propDesc As PropertyDescriptor in properties
row[propDesc:Name] := propDesc:GetValue(item)
next
ta:Rows:Add(row)
next
catch ex As SystemException
Console.WriteLine("!!! Fehler in Convert2DataTable (" + ex:Message + ") !!!")
end try

Return ta

End Class

Danach besitzt eine generische Liste automatisch eine Convert2DataTable-Methode:
Local DokListe := List<Dokument>{} As List<Dokument>
...
Local taDok = DokListe.Convert2DataTable() As DataTable

Das geht alles auch ohne Extension Method, aber der Code wird besser lesbar und man kann leichter Programmcode aus der C#-Welt übernehmen;)
User avatar
wriedmann
Posts: 3649
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Extensions

Post by wriedmann »

Hallo Peter,

ja, extension methods haben schon was für sich.... in meiner BaseLib gibt es da jede Menge Methoden, die sich an die String-Klasse oder an die DateTime-Klasse dranhängen.
Und was Datenzugriff betrifft: mich hat es immer genervt, dass ich beim Zugriff auf DataRow.Inhalte oft casten muss, also gibt es bei mir auch entsprechende Anhängsel der DataRow-Klasse:

Code: Select all

public static method GetString( self oDataRow as DataRow, cFieldName as string ) as string
local oValue as object
local cReturn as string

cReturn := ""
oValue := oDataRow[cFieldName]
if oValue == DBNull.Value
  cReturn := ""
else
  cReturn := oValue:ToString()
endif
return cReturn
(Errorhandling habe ich der Einfachheit halber rausgenommen).
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Post Reply