Všechno nejlepší do Nového roku 2014, hodně čistého a znovupoužitého kódu, který přežije nejeden projekt.
A hlavně zdravíčko a dobré přátele.
úterý 31. prosince 2013
středa 4. prosince 2013
Immutable collections in .NET
Spojování dvou a více .NET Assembly.
Pokud programujete v C nebo C++, tak jistě víte, že knihovny lze linkovat do výsledné aplikace staticky nebo dynamicky. Pokud linkujete staticky, tak se vám knihovny připojí k výsledné aplikaci a nepotřebujete nic dalšího k aplikaci přidávat. Pokud linkujete dynamicky musíte mít společně s aplikací také dynamické knihovny dll.
V prostředí .NET ale jsou knihovny referencované dynamicky a s aplikací teda potřebujete i .NET dll knihovny.
Tak mě napadlo, jestli by nešlo .NET assembly slinkovat také staticky. Vše nasvědčuje tomu, že žádné statické slinkování nenní možné jak jsme byli zvyklí z céčka.
Googloval jsem na netu a řešením je spojení více assembly do jedné použitím utility ILMerge.exe
ILMerge
V prostředí .NET ale jsou knihovny referencované dynamicky a s aplikací teda potřebujete i .NET dll knihovny.
Tak mě napadlo, jestli by nešlo .NET assembly slinkovat také staticky. Vše nasvědčuje tomu, že žádné statické slinkování nenní možné jak jsme byli zvyklí z céčka.
Googloval jsem na netu a řešením je spojení více assembly do jedné použitím utility ILMerge.exe
ILMerge
čtvrtek 28. listopadu 2013
GIT - aplikace patche
Na správu mého GIT repozitáře, použivam SourceTree od Atlassianu. Aktuální verze 1.3.2 neumí vytvářet patche do souboru a následně je aplikovat v jiné větvi. Přes git konzoli to alr není žádný problém.
$ git format-patch BruceLee --stdout > z:/lib.patch
Git vytvořil z podsledního komitu větve BruceLee rozdílový soubor a uložil ho do z:/lib.patch.
Nyní se můžete přepnout do větve, kde chcete patch aplikovat.
Aplikaci patche můžete otestovat.
$git apply --check z:/lib.patch
A pokud je vše v pořádku, můžeme patch aplikovat.
git am --signoff < z:/lib.patch
$ git format-patch BruceLee --stdout > z:/lib.patch
Git vytvořil z podsledního komitu větve BruceLee rozdílový soubor a uložil ho do z:/lib.patch.
Nyní se můžete přepnout do větve, kde chcete patch aplikovat.
Aplikaci patche můžete otestovat.
$git apply --check z:/lib.patch
A pokud je vše v pořádku, můžeme patch aplikovat.
git am --signoff < z:/lib.patch
středa 20. listopadu 2013
čtvrtek 7. listopadu 2013
ASP .NET MVC - hostování webové aplikace v konzolové aplikaci
Pojďme se podívat zase na jeden problém z vývojářského života. Máme svůj vlastní klient - server systém a server nám běží jako služba ve windows nebo jako konzolová aplikace. Jedná se o náš vlastní server. Tento server má přístup do SQL a data zpřístupňuje pro klienty pomocí webových služeb. Protože dotazy na některá data jsou časově náročné, server si udržuje vlastní cache.
Já bych potřeboval do tohoto serveru přidat další modul (dll), který se při startu zavede pomocí MEF. Já bych potřeboval, aby tento modul poskytoval webovou aplikaci ASP .NET MVC - Razor. Myslel jsem si, že to nebude vůbec žádný problém, protože já již umím hostovat MVC Web API. K tomu se používá třída
Hostování Web API mám vyzkoušené a funguje bez problému, tak jsem zkoušel také nahostovat webovou aplikaci která hostuje MVC stránky s enginem Razor.
Řešení jsem prozatím nenašel, berte to špíše jako položenou otázku a sběr informací.
Jedna možnost je použití knihovny RazorEngine. Pokud se chcete vyhnout neoficiálním knihovnám třetích stran, pojďme ještě hledat dál.
Dále je možné hostovat webovou aplikaci pomocí
Já bych potřeboval do tohoto serveru přidat další modul (dll), který se při startu zavede pomocí MEF. Já bych potřeboval, aby tento modul poskytoval webovou aplikaci ASP .NET MVC - Razor. Myslel jsem si, že to nebude vůbec žádný problém, protože já již umím hostovat MVC Web API. K tomu se používá třída
HttpSelfHostServer
Tutorial o ASP .NET Self hosting WebAPIHostování Web API mám vyzkoušené a funguje bez problému, tak jsem zkoušel také nahostovat webovou aplikaci která hostuje MVC stránky s enginem Razor.
Řešení jsem prozatím nenašel, berte to špíše jako položenou otázku a sběr informací.
Jedna možnost je použití knihovny RazorEngine. Pokud se chcete vyhnout neoficiálním knihovnám třetích stran, pojďme ještě hledat dál.
Dále je možné hostovat webovou aplikaci pomocí
IIS 7.0 Hostable Web Core
pondělí 21. října 2013
C# JSON Serializace a deserializace polymorfních objektů
C# JSON Serializace a deserializace polymorfních objektů -rozepsané
Po dlouhé době jsem narazil na zajímavý problém. Potřebuji uložit data do formátu JSON ale každá datová položka je jiný typ. Jedná se o tzv. polymofní typ. Například chci si uložit databázi zvířat (animals) a mám definovaný obecný objekt animal a pak mám definované konkrétní typy Cat, Lion, Horse. A každý typ má trochu jiné vlastnosti.
Podívejme se na můj konkrétní případ: Mám pole nějakých objektů, které představují nějaké nastavení. Každá položka v poli má své jméno Name a hodnotu Value.
Defaultní JSON serializér mi udělal jednoduchý JSON, ale nešlo rozeznat Typy Value. Udělal jsem si pro každý datový typ speciální variantu:
Pokud použiji defaultní serializér:
Na rozlišení typů jsem si našel jiný serializer, který se nacháyí v System.Web.Extensions.
K tomu musíte ješte připsat JavaScriptTypeResolver:
Zpětně jde výsledek zase serializovat:
Výsledek už nevypadá tak hezky, ale informaci o typu zde již máme.
Po dlouhé době jsem narazil na zajímavý problém. Potřebuji uložit data do formátu JSON ale každá datová položka je jiný typ. Jedná se o tzv. polymofní typ. Například chci si uložit databázi zvířat (animals) a mám definovaný obecný objekt animal a pak mám definované konkrétní typy Cat, Lion, Horse. A každý typ má trochu jiné vlastnosti.
Podívejme se na můj konkrétní případ: Mám pole nějakých objektů, které představují nějaké nastavení. Každá položka v poli má své jméno Name a hodnotu Value.
public class OptionValue { [DataMember] public string Name { get; set; } [DataMember] public object Value { get; set; } }
[DataContract] public class IntValue { public IntValue() { } public IntValue(string name) { Name = name; } [DataMember] public string Name { get; set; } [DataMember] public new Int32 Value { get; set; } } [DataContract] public class BoolValue { public BoolValue() { } public BoolValue(string name) { Name = name; } [DataMember] public string Name { get; set; } [DataMember] public new bool Value { get; set; } } [DataContract] public class StringValue { public StringValue() { } public StringValue(string name) { Name = name; } [DataMember] public string Name { get; set; } [DataMember] public new String Value { get; set; } } [DataContract] public class TimeValue { public TimeValue() { } public TimeValue(string name) { Name = name; } [DataMember] public string Name { get; set; } [DataMember] public new TimeSpan Value { get; set; } } [DataContract] public class DateValue { public DateValue() { } public DateValue(string name) { Name = name; } [DataMember] public string Name { get; set; } [DataMember] public new DateTime Value { get; set; } }
msg = Request.CreateResponse(HttpStatusCode.OK,array, "application/json");
dostanu výsledek, kde nevím, jakého typu mám položky.
[{"Name":"DefaultSection","Value":"SatelliteHolder"},{"Name":"FillInterfaceName","Value":"Bonus"},{"Name":"FillFilterName","Value":"SATELLITE FILL"},{"Name":"FillSection:Position","Value":"end"},{"Name":"FillSection:Position","Value":"end"},{"Name":"FillSection:Position","Value":"end"},{"Name":"ConfigFillSectionType","Value":"SpotsetHolder"},{"Name":"MinAllowFillDistance","Value":240},{"Name":"MinGroupFillDistance","Value":10},{"Name":"SeparationFilterName","Value":"SATELLITE SEPARATION"},{"Name":"FillFilterSkip","Value":"SATELLITE SKIP"},{"Name":"ConfigSkipSectionType","Value":"SpotsetHolder"},{"Name":"Performance","Value":false},{"Name":"VisibleSections","Value":"HourHeader|SatelliteHolder"}]
string json = new JavaScriptSerializer(new TypeResolver()).Serialize(o); msg = Request.CreateResponse(HttpStatusCode.OK,json, "application/json");
public class TypeResolver : JavaScriptTypeResolver { public override Type ResolveType(string id) { if (id == "string") { return new StringValue().GetType(); } else if (id == "int") { return new IntValue().GetType(); } else if (id == "bool") { return new BoolValue().GetType(); } else if (id == "float") { return new FloatValue().GetType(); } else if (id == "time") { return new TimeSpan().GetType(); } else if (id == "date") { return new DateTime().GetType(); } return new object().GetType(); } public override string ResolveTypeId(Type type) { if (type.Name == "StringValue") return "string"; else if (type.Name == "IntValue") return "int"; else if (type.Name == "BoolValue") return "bool"; else if (type.Name == "FloatValue") return "float"; else if (type.Name == "TimeValue") return "time"; else if (type.Name == "DateValue") return "date"; return "anyType"; }
object obj = new JavaScriptSerializer(new TypeResolver()).Deserialize<Options>(json);
"[{\"__type\":\"string\",\"Name\":\"DefaultSection\",\"Value\":\"SatelliteHolder\"},{\"__type\":\"string\",\"Name\":\"FillInterfaceName\",\"Value\":\"Bonus\"},{\"__type\":\"string\",\"Name\":\"FillFilterName\",\"Value\":\"SATELLITE FILL\"},{\"__type\":\"string\",\"Name\":\"FillSection:Position\",\"Value\":\"end\"},{\"__type\":\"string\",\"Name\":\"FillSection:Position\",\"Value\":\"end\"},{\"__type\":\"string\",\"Name\":\"FillSection:Position\",\"Value\":\"end\"},{\"__type\":\"string\",\"Name\":\"ConfigFillSectionType\",\"Value\":\"SpotsetHolder\"},{\"__type\":\"int\",\"Name\":\"MinAllowFillDistance\",\"Value\":240},{\"__type\":\"int\",\"Name\":\"MinGroupFillDistance\",\"Value\":10},{\"__type\":\"string\",\"Name\":\"SeparationFilterName\",\"Value\":\"SATELLITE SEPARATION\"},{\"__type\":\"string\",\"Name\":\"FillFilterSkip\",\"Value\":\"SATELLITE SKIP\"},{\"__type\":\"string\",\"Name\":\"ConfigSkipSectionType\",\"Value\":\"SpotsetHolder\"},{\"__type\":\"bool\",\"Name\":\"Performance\",\"Value\":false},{\"__type\":\"string\",\"Name\":\"VisibleSections\",\"Value\":\"HourHeader|SatelliteHolder\"}]"
pátek 22. března 2013
Věčný problém s parsováním parametrů URL
Opakovaně řeším v serverové službě problém s parsováním parametrů.
Parse Query string
Řešení je velmi jednoduché. Musíte dostat korektní QueryString, který má nahrazené řídící znaky escape sekvencí.
- Když jsem si službu napsal jako WCF REST, tak jsem zjistil, že WCF neumí pracovat s dynamickým počtem parametrů. Tak jsem dynamické parametry zakódoval do stringu. Vše se zdálo v pohodě až do chvíle, kdy se v parametrech objevilo '/' nedokáže WCF příjmout HTTP request. Vadí mu lomítko navíc. Zde jsem řešení nenašel
- Když jsem službu napsal jako HttpListener, tedy pouze jednoduchý zachytávač HTTP requestů, tak jsem narazil na podobný problém se znakem '&'.
Parametry jsem si naparsoval pomocí utility:NameValueCollection qscoll = HttpUtility.ParseQueryString(querystring);
http://localhost:8128/Action/ActionExecute/command=c:/notepad&.exe Dostal jsem výsledek: 0) command=c:\notepad 1) null = .exe
Jak z toho ven (sto hoven)?
Parse Query string
Řešení je velmi jednoduché. Musíte dostat korektní QueryString, který má nahrazené řídící znaky escape sekvencí.
pondělí 18. března 2013
Kroutím hlavou
string stanice="frekvence1";
Public string get()
{
string stanice="kiss";
return stanice;
}
čtvrtek 7. března 2013
Window Manager
Přemýšlím, jak do aplikačního frameworku MEF, Prism začlenit Windows manager
Inspirace:
http://www.codeproject.com/Articles/249261/How-To-Embed-An-Application-Into-a-Docking-Library
Přihlásit se k odběru:
Příspěvky (Atom)