Laden...

FileSearch Komponente

Erstellt von Dan vor 18 Jahren Letzter Beitrag vor 14 Jahren 11.934 Views
D
Dan Themenstarter:in
124 Beiträge seit 2005
vor 18 Jahren
FileSearch Komponente

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 😉

N
118 Beiträge seit 2004
vor 18 Jahren

Am ende des Headers fehlt ein

#endregion

🙂

C
1.215 Beiträge seit 2004
vor 18 Jahren

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

grüsse

Q
992 Beiträge seit 2005
vor 18 Jahren

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

D
Dan Themenstarter:in
124 Beiträge seit 2005
vor 18 Jahren

Hi,

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

Dan

S
709 Beiträge seit 2005
vor 18 Jahren

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! 👍

Q
992 Beiträge seit 2005
vor 18 Jahren

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

Grüße Christoph

C
1.215 Beiträge seit 2004
vor 18 Jahren

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

Q
992 Beiträge seit 2005
vor 18 Jahren

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.

C
980 Beiträge seit 2003
vor 18 Jahren

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"); });
C
1.215 Beiträge seit 2004
vor 18 Jahren

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

Q
992 Beiträge seit 2005
vor 18 Jahren

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.

C
980 Beiträge seit 2003
vor 18 Jahren

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?)

Q
992 Beiträge seit 2005
vor 18 Jahren

Original von cdr

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

C
980 Beiträge seit 2003
vor 18 Jahren

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

B
101 Beiträge seit 2008
vor 14 Jahren

Ein kleines Beispiel wäre nicht schlecht.

Bei mir funktionierts wegen fehlenden Rechten nicht ganz.

lg Norbert

5.941 Beiträge seit 2005
vor 14 Jahren

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