Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
FileSearch Komponente
Dan
myCSharp.de - Member



Dabei seit:
Beiträge: 124
Herkunft: Munich

Themenstarter:

FileSearch Komponente

beantworten | zitieren | melden

Hi,

wie bereits in diesem Thread erwähnt, kann ich eine FileSearch Komponente zur Verfügung stellen.

Diese ist inklusive Source und Doku als Attachment beigefügt:

Momentane Features:
- Synchrone (normale) und asynchrone Dateisuche
- Vielzahl von Einstellungsmöglichkeiten:
|- Standardsuche mit Wildcards (*.* usw.)
|- Suche einschränken mit Regulären Ausdrücken
|- Suche anhand der Dateigröße einschränken
|- Suche anhand von Dateiattributen einschränken
|- Suche anhand von Datumswerten einschränken (Erzeugungsdatum, Zuletzt geändert und Zeit des letzten Zugriffs)
|- Durchsuchen von Textpassagen in (Text)Dateien (noch ausbaufähig)

Das Ganze kann beliebig erweitert werden, z.B. Suche eingrenzen anhand von MP3 ID3 Tags, Bildgrösse oder ähnlichem.

Die Basis für alle Suchoptionen ist die Schnittstelle "ISearchOption":

public interface ISearchOption
{
	/// <summary>
	/// The result of this method determines whether a found file matches a specific criteria.
	/// </summary>
	/// <param name="fi">The <see cref="FileInfo"/> object for the found file.</param>
	/// <returns>True, if the result matches. False otherwise.</returns>
	bool Match(FileInfo fi);
}

So könnt ihr ganz leicht eigene Suchkriterien coden, z.B. für die Größe eines Bildes:

public class ImageDimensionSearchOption : ISearchOption
{
	int m_MinimumWidth;
	
	public ImageDimensionSearchOption(int MinimumWidth)
	{
		this.m_MinimumWidth = MinimumWidth;
	}
	
	public bool Match(FileInfo fi)
	{
		using(FileStream fs = fi.OpenRead())
		{
			// It's a PNG Image
			if( String.Compare(Path.GetExtension(fi.FullName), ".png", true) == 0 )
			{
				// fs.Read...
				// die Breite des PNG Bildes auslesen. int imgWidth = ...;
				// return imgWidth ≥ this.m_MinimumWidth;
			}
			else if...
		}
	}
}
Diese Kriterium könnt ihr dann den Suchoptionen hinzufügen:

// Nur nach Bildern suchen, welche mindestens 200 pixel breit sind
fileSearch.Options.Add(new ImageDimensionSearchOption(200));
Eigentlich ziemlich straight forward.

Verbesserungsvorschläge und Kommentare sind ausdrücklich erwünscht
Attachments
private Nachricht | Beiträge des Benutzers
Nostalb
myCSharp.de - Member



Dabei seit:
Beiträge: 118

beantworten | zitieren | melden

Am ende des Headers fehlt ein

#endregion

private Nachricht | Beiträge des Benutzers
Cord Worthmann
myCSharp.de - Member



Dabei seit:
Beiträge: 1.203

beantworten | zitieren | melden

schön gelöst.
dieses beispiel könnte hervorragend für zukünftige fragen "Was ist eigendlich genau ein Interface?" herhalten.
:-)


grüsse
private Nachricht | Beiträge des Benutzers
Quallo
myCSharp.de - Member



Dabei seit:
Beiträge: 992
Herkunft: Nähe Bremen

beantworten | zitieren | melden

Sieht sehr nett und nach viel Arbeit aus!

Wie sieht es mit der Performance bei der Suche aus?
Wurde das getestet? Mich würde das Resultat bei einem Single-Core, einem Single-Core HyperThreading, einem Dual-Core und einem Dual-Core mit Hyper-Threading interessieren. ?(

Gute Arbeit!

Grüße, Christoph
private Nachricht | Beiträge des Benutzers
Dan
myCSharp.de - Member



Dabei seit:
Beiträge: 124
Herkunft: Munich

Themenstarter:

beantworten | zitieren | melden

Hi,

erstmal danke für das positive Feedback.
Die Performance hab ich nicht gemessen, aber das werd ich in nächster Zeit nachholen.

Dan
private Nachricht | Beiträge des Benutzers
SimonKnight6600
myCSharp.de - Member



Dabei seit:
Beiträge: 709
Herkunft: Österreich

beantworten | zitieren | melden

Ich wollte auch ne FileSearch Komponente machen, habs aber dann aufgegeben. Mit deiner Komponente hätte meine sowieso kein Stück mithalten können. Sehr gute Arbeit!
private Nachricht | Beiträge des Benutzers
Quallo
myCSharp.de - Member



Dabei seit:
Beiträge: 992
Herkunft: Nähe Bremen

beantworten | zitieren | melden

Wo genau liegt jetzt der Vorteil der Interfaces?
Hätte man den Fall nicht auch mit Events + Delegates abhandeln können?

Grüße Christoph
private Nachricht | Beiträge des Benutzers
Cord Worthmann
myCSharp.de - Member



Dabei seit:
Beiträge: 1.203

beantworten | zitieren | melden

ich denke, dass events dafür nicht gedacht sind, da es um keinen unvorhersehbaren vorgang geht sondern eine simple iteration durch verzeichnis-inhalte - und das wäre damit eine rein sequenzielle arbeitsweise, welche das gegenteil von der ereignisbehafteten arbeitsweise ist.


grüsse
private Nachricht | Beiträge des Benutzers
Quallo
myCSharp.de - Member



Dabei seit:
Beiträge: 992
Herkunft: Nähe Bremen

beantworten | zitieren | melden

Ich finde es aber auch ein Ereignis, wenn bei einer Interation ein möglicher Kandidat überprüft werden muss.
Sind denn Events und delegates langsamer?

Ich sehe es so, dass man Klassen mit einer Schnittstelle, die eine Methode implementiert, auch durch Events erledigen kann, wäre aber dankbar für die Widerlegung dieser Theorie. Erweiterbarkeit könnte eine Rolle spielen, falls ich pro Klasse 2 oder n Methoden implementiere brauche ich die nur einmal anmelden.
private Nachricht | Beiträge des Benutzers
cdr
myCSharp.de - Member



Dabei seit:
Beiträge: 980
Herkunft: Zürich

beantworten | zitieren | melden

in v1.1 sind Interfaces etwas langsamer, Delegates massiv langsamer
in v2.0 sind Interfaces nicht mehr langsamer, Delegates aber leider immer noch langsam.

Note: Ereignisse haben keine Rückgabewerte, folglich liesse sich z.b. das ISeachOption schon rein technisch nicht als Event umschreiben.

Trotzdem wirst du für ein solches Predicate Design Pattern in C# 2 (in C# 1 ich persönlich eher nicht) wahrscheinlich ein Delegate nehmen (dass in Praxis dann wohl als Anonyme Methode übergeben wird). Wird auch im neuen Framework so gelöst, siehe z.b. die Array Klasse:

public static T[] System.Array.FindAll<T>(T[] array, Predicate<T> match);

Anwendung:

string[] mystrings = ...;
string[] stringsStartWithABC = Array.FindAll<string>(mystrings,delegate(string value) { return value.StartsWith("ABC"); });
private Nachricht | Beiträge des Benutzers
Cord Worthmann
myCSharp.de - Member



Dabei seit:
Beiträge: 1.203

beantworten | zitieren | melden

Zitat
Original von Quallo
Ich finde es aber auch ein Ereignis, wenn bei einer Interation ein möglicher Kandidat überprüft werden muss.
Sind denn Events und delegates langsamer?
welche die schnellere methode ist, weiss ich nicht.
man könnte das natürlich auch über events erledigen.
...aber es ist ganz sicher keine ereignisbehaftete prozedur, wenn man durch die dateien eines verzeichnisses iteriert.
ereignisse treten unvorhersehbar ein - dass jetzt aber gleich die nächste und danach die wiederum folgende datei dran kommt, weisst du sehr wohl, wenn du dich innerhalb dieses prozedur befindest.


grüsse
private Nachricht | Beiträge des Benutzers
Quallo
myCSharp.de - Member



Dabei seit:
Beiträge: 992
Herkunft: Nähe Bremen

beantworten | zitieren | melden

Zitat
Original von cdr
Note: Ereignisse haben keine Rückgabewerte

Müssen delegates immer vom Typ void sein?
Kann man delegates nicht auch ohne Event verwenden?

Man kann aber doch eine Bool-Variable mitgeben und die im delegate verändern.

Fragen über Fragen, ich weiß, aber das interessiert mich halt sehr, da ich ein ähnliches Problem gerade mit Events gelöst habe.

Danke erstmal für eure Antworten, so langsam kommen ja ein paar Gründe zusammen, warum man Interfaces nehmen sollte.
private Nachricht | Beiträge des Benutzers
cdr
myCSharp.de - Member



Dabei seit:
Beiträge: 980
Herkunft: Zürich

beantworten | zitieren | melden

Zitat
Original von Quallo
Müssen delegates immer vom Typ void sein?
Kann man delegates nicht auch ohne Event verwenden?

Nein, Delegates können (i.a.) beliebige Rückgabewerte haben (und ja, man kann sie unabhängig von Events verwenden). Das funktioniert dann auch (und entspricht in etwa meinem Beispiel oben). Allerdings kann man solche Delegates dann nicht als Events verwenden (Events sind Multicast Delegates, die alle 'Subscriptions' in unbekannter Reihenfolge ausführen. Welcher der Rückgaberwerte der verschiedenen Subscriptions sollte dann dem Event-Aufrufer von der CLR zurückgegeben werden?)
private Nachricht | Beiträge des Benutzers
Quallo
myCSharp.de - Member



Dabei seit:
Beiträge: 992
Herkunft: Nähe Bremen

beantworten | zitieren | melden

Zitat
Original von cdr
Zitat
Original von Quallo
Müssen delegates immer vom Typ void sein?
Kann man delegates nicht auch ohne Event verwenden?

Nein, Delegates können (i.a.) beliebige Rückgabewerte haben (und ja, man kann sie unabhängig von Events verwenden). Das funktioniert dann auch (und entspricht in etwa meinem Beispiel oben). Allerdings kann man solche Delegates dann nicht als Events verwenden (Events sind Multicast Delegates, die alle 'Subscriptions' in unbekannter Reihenfolge ausführen. Welcher der Rückgaberwerte der verschiedenen Subscriptions sollte dann dem Event-Aufrufer von der CLR zurückgegeben werden?)


Ok, dann ändere ich meine Frage in: Kann man das nicht mit delegates statt Interfaces behandeln?

Grüße Christoph
private Nachricht | Beiträge des Benutzers
cdr
myCSharp.de - Member



Dabei seit:
Beiträge: 980
Herkunft: Zürich

beantworten | zitieren | melden

Kann man. Es ist dann einfach etwas langsamer in v1.1 (in v2 sollten Delegates fast gleich schnell sein wie Interfaces - habe allerdings auch schon mal das gegenteil gehört, müsste es also mal selber messen). Dafür wiederum etwas flexibler ...

Vergleich:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp02172004.asp
private Nachricht | Beiträge des Benutzers
bCoderer
myCSharp.de - Member



Dabei seit:
Beiträge: 101

beantworten | zitieren | melden

Ein kleines Beispiel wäre nicht schlecht.

Bei mir funktionierts wegen fehlenden Rechten nicht ganz.

lg Norbert
private Nachricht | Beiträge des Benutzers
Peter Bucher
myCSharp.de - Experte

Avatar #jVxXe7MDBPAimxdX3em3.jpg


Dabei seit:
Beiträge: 5.940
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Salute Norbert

Wenn du das jetzt mit dieser Komponente umsetzen möchtest, könnte das bspw. so gehen:


public class DelegateSearchOption : ISearchOption
{
    private readonly Func<FileInfo, bool> _filter;

    public DelegateSearchOption(Func<FileInfo, bool> filter)
    {
        this._filter = filter;
    }

    public bool Match(FileInfo fileInfo)
    {
        return this._filter();
    }
}

Und die Benutzung bspw.:


XYZ.Options.Add(new DelegateSearchOption(f => File.GetExtension(f.Name).Equals("gif")));

// [...]


Gruss Peter
--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

- https://peterbucher.ch/ - Meine persönliche Seite
- https://fpvspots.net/ - Spots für FPV Dronenflüge
private Nachricht | Beiträge des Benutzers