Also ich hab mir aus Github den Master runtergeladen und da kommt das Minify definitiv danach. Ich hab zum Spaß einfach mal ein Thread.Sleep(100) (nach dem Minify) eingefügt und die Ausgabe auf der Webseite war weiterhin unter 100 Ticks. Oder verwendest du eine andere Version?
Bzgl. dem Block-basiert: Dein Quellcode zeigt doch, dass du in der Write-Methode mit dem übergebenen Buffer und damit nicht mit dem gesamten HTML auf einmal arbeitest. Du wirst beim Debuggen sicher sehen, dass mehrmals in die Write-Methode gesprungen wird.
Übrigens kann ich mir das mit den 2ms nicht wirklich vorstellen. Mein Rechner benötigt für folgendes schon länger als 3ms:
Pattern nur bedingt korrekt: Das Regex pattern matched nur aufeinanderfolgende Whitespaces und lässt das erste stehen, d.h. es werden z.b. nicht alle Zeilenumbrüche entfernt wie angegeben, sondern aus \r\n wird \r. Das lässt sich noch optimieren.
Problem mit <pre> Tags: Dein Regex-Pattern versucht zwar diese Problem zu lösen, allerdings wäre das so nur korrekt, wenn du dein Regex auf den kompletten HTML-String anwendest. Du arbeitest in der Write-Methode aber Block-basiert, d.h. ein </pre>-Tag könnte erst im nächsten Block enden, wodurch du fälschlicherweise die Whitespaces entfernen würdest.
Performance: Die von dir genutzte Performance-Messung macht keinen Sinn, da die OnActionExecuted-Methode deines Filters (und damit das Ende der Messung) aufgerufen wird, bevor die eigentliche Minification stattfindet. Wenn du misst wie lange das eigentliche Minifizieren dauert, wirst du sehen, dass es einen wahnsinnig hohen Performance Impact hat. Ich habe eine kurze Messung gemacht, mit und ohne Minifikation (jeweils 100 Durchläufe). Das Ergebnis ist als Boxplot unten beigefügt.
Dann weist du deiner XML-Datei als Custom-Tool einfach T4ScriptFileGenerator zu und bei jeder Speicherung deiner XML-Datei wird das entsprechende Script getriggert.
das Problem ist, dass deine Methode "ShowContactWithParameter" nicht die Signatur eines Action-Delegates hat, sondern die Signatur von Action<string>.
Aber bei diesem Ansatz muss dann natürlich auch jemand eine Parameter übergeben. Ich sehe nicht, wie das über die Zuweisung an ein MenuItem sinnvoll möglich sein soll.
Naja, wenn du deine Werte aus der Datei liest, liegen sie aber erstmal als string vor und nicht als int. Das musst du dann so oder so parsen, aber das beziehst du in deinem Szenario nicht mit ein, was natürlich das Ergebnis verfälscht.
ohne deine Lösung schlecht machen zu wollen, ist das Testszenario doch sehr praxisfremd.
Die 3 int-Werte müssen ja irgendwo herkommen, aus einem Textfile oder Datenbank etc., d.h. sie liegen nicht schon als int vor, es sei denn du speicherst sie in der DB als int und nicht als DateTime, was aber total praxisfremd wäre.
D.h. für einen fairen Vergleich, musst du davon ausgehen dass die Eingaben als String vorliegen. Diesen müsstest du dann erst in deine int-Komponenten zerlegen.
D.h. fair/realistisch wäre folgendes:
for (l1 = 0; l1 < max; l1++)
{
var parts = "31.01.2005".Split('.').Select(f => int.Parse(f)).ToArray();
korrekt = pruefe_datum(parts[2], parts[0], parts[1]);
}
Dann wirst du sehen, dass gegenüber der DateTime.TryParse-Methode keine zeitliche Verbesserung stattfindet.
for (l1 = 0; l1 < max; l1++)
{
DateTime dt;
korrekt = DateTime.TryParse("31.01.2005", out dt);
}
Ich denke von der Architektur her solltest du komplett auf den Parameter in der execute-Methode verzichten, denn du willst ja gerade nicht, dass sich der Aufrufer Gedanken darüber machen muss, ob er jetzt ein File übergeben muss oder nicht, denn dazu müsste er ja wieder wissen um welchen Command es sich handelt.
Abhängig von deiner bisherigen Architektur wäre es evtl. besser diesen Command-spezifischen Kontext über den Konstruktor des jeweiligen Commands bereitzustellen. Aber das ist natürlich abhängig davon wie du die Commands tatsächlich verwenden möchtest.
Ein Test hat gezeigt, dass ab einer Kombination von 2048 Bildern (2048 * 16 = 32768) ein Problem entsteht. Das hängt evtl. mit GDI+ zusammen (GDI+ Bitmap size limitation?).
Ich denke das ist schonmal ein Ansatz für die weitere Recherche.
der Code sieht gut aus.
Ich habe es mal mit zwei Icons versucht und habe kein Problem mit der Anzeige im Browser.
Evtl. ist ja eines der Icons fehlerhaft und Paint.NET korrigiert das bei der Speicherung.
Die Datei nach jeder Zeilenbearbeitung neu zu schreiben ist nicht sinnvoll.
Mach es so wie Palladin007 es in seinem ersten Post beschrieben hat und filtere einfach die Zeilen die beibehalten werden sollen und schreibe diese dann gesammelt auf die Platte.
Du musst nur noch die von Palladin007 genannte Methode DoWorkWithLines ordentlich implementieren.
Damit erhältst du ein Bitmap-Objekt, welches du dann als TIFF abspeichern kannst.
Allerdings unterliegt MuPDF der GPL, d.h. wenn du es kommerziell nutzen möchtest, musst du dich auch an die GPL halten.
Schlauer wäre es die Methoden gleich als Delegates abzulegen, dann hast du auch keine Magic-Strings.
Z.b. so in etwa (abhängig davon wie deine Methodensignaturen aussehen):
var actions = new Dictionary<string, Action>();
actions.Add("SNR", SaveSN);
...
var a =actions["SNR"]; // Action holen
a(); // Aufruf der Methode
...
private void SaveSN()
{
...
}
Alternativ kannst du auch den generische Action-Delegate verwenden, oder Func<> wenn deine Methoden Rückgabewerte haben.
Selbst wenn es funktioniert, brauche ich aber zusätzlich auch noch die Werte aus den Gruppen, kann ich da überhaupt über den Index auf die Gruppe für die erste Zahl zugreifen, oder habe ich am Ende dann nur eine Gruppe, die beide Zahlen validiert und ich bekomme nur die Zweite?
Du kannst auch benannte Gruppen verwenden:
var pattern = @"^(?<min>(-?\d+(\.\d+)?)?)\-(?<max>(-?\d+(\.\d+)?)?)$";
var regex = new Regex(pattern);
Func<string, double?> toDoubleOrNull = f => string.IsNullOrEmpty(f) ? (double?)null : Convert.ToDouble(f);
foreach (var item in asdf)
{
var m = regex.Match(item);
if (m.Success)
{
var min = toDoubleOrNull(m.Groups["min"].Value);
var max = toDoubleOrNull(m.Groups["max"].Value);
}
}
meinst du mit mehreren Typangaben so etwas in der Art?
class Program
{
static void Main(string[] args)
{
var mi = typeof(Program).GetMethods().Where(f => f.Name == "DoIt" && f.GetGenericArguments().Length == 2).FirstOrDefault();
if (mi != null)
{
mi = mi.MakeGenericMethod(typeof(string), typeof(int));
var res = mi.Invoke(new Program(), new object[] { "Hello", 123 });
Console.WriteLine(res.ToString());
}
}
public A DoIt<A, B>(A a, B b)
{
return a;
}
public C DoIt<A, B, C>(A a, B b, C c)
{
return c;
}
}
je nach Anwendungsfall könntest du es auch mittels Generics lösen, z.B.:
public abstract class Generator<T> where T : IParameter
{
public abstract string Generate(T input);
}
public class NameGenerator : Generator<NameParameter>
{
public override string Generate(NameParameter input)
{
throw new NotImplementedException();
}
}
public interface IParameter
{ }
public class NameParameter : IParameter
{
public string Name { get; set; }
}
also die Aussage "extrem stümperhaft" ist übertrieben.
Ich gebe dir zwar recht, dass das fehlende Dispose unschön ist, aber im genannten Fall hat es ohnehin keine Bedeutung, da weder StringWriter, noch die Basisklasse TextWriter irgendwelche Resourcen innerhalb der Dispose-Methode freigeben und damit ein fehlendes Dispose keine Speicherproblem verursacht.
ich bin der Entwickler von MoonPdf. Falls du ein konkretes Problem damit hast, kannst du mich gerne fragen.
Bzgl. Makefile sollte alles nötige hier stehen: MoonPdfPanel - A WPF-based PDF viewer control
Über das makefile wird die MuPdf "libmupdf.dll" erzeugt. Du kannst diese dll theoretisch auch aus den Binaries nehmen und in das entsprechende Verzeichnis ("bin/MuLib/$(platform)") kopieren.
wenn alle Dateinamen in der Form aufgebaut sind, dann geht es ja nur drum den ersten space zu erkennen und dann quasi bis zum punkt alles zu entfernen.
Mit Regex könnte das in etwa so aussehen (ungetestet):
([^\s]+)[^.]+(\..+)
Damit hättest du dann die zwei gruppen für Dateiname und Dateiendung und das Replace pattern könnte abhängig vom Regex flavor z.B. so aussehen: