Category Archives: .NET Framework

Programátorská hádanka: Exceptions

Co bude výstupem?

try
{
  try
  {
    throw new Exception("A");
  }
  catch
  {
    throw new Exception("B");
  }
  finally
  {
    throw new Exception("C");
  }
}
catch (Exception ex)
{
  Console.Write(ex.Message);
}

Výsledek: https://dotnetfiddle.net/6SWPqL

Quartz.NET, Castle Windsor – LifeStyle Per Job (Scoped)

Pokud používáte Quartz.NET (známá knihovna pro job-scheduling) s Castle Windsor (IoC/DI container), možná jste narazili na potřebu registrovat komponentu s životním cyklem „per job“ (LifestylePerJob). Na internetu najdete několik možností, které mají jedno společné – nefungují:

  • LifestylePerThread – neresetuje thread mezi joby, komponenta se použije pro více jobů
  • BoundTo<Job>() – nepodporuje typed factories, pokud si z nich vyžádáte službu v jobu
  • BoundTo<object>() – nepodporuje typed factories, pokud si z nich vyžádáte službu v jobu
  • Quartz.IJobFactory + LifestyleScoped – nepodporuje typed factories, pokud si z nich vyžádáte službu v jobu (scope odstartovaný v JobFactory se nezpropaguje do jobu!)

Naštěstí existuje „jednoduché“ řešení. Můžete použít LifestyleScoped, ale je potřeba scope začít/ukončit uvnitř jobu.

Pokud použijete samotný job jenom jako plumbing class kde práce samotná je zapouzdřena do samostatné služby (a měli byste to tak mít tak jako tak), pak stačí do jobu nainjectovat factory k takové službě a kernel pro ovládání scope:

public class MyJob : IJob
{
    private readonly IServiceFactory&lt;myservice&gt; myServiceFactory;
    private readonly IKernel kernel;

    public MyJob(IServiceFactory&lt;myservice&gt; myServiceFactory, IKernel kernel)
    {
        this.myServiceFactory = myServiceFactory;
        this.kernel = kernel;
    }

    public void Execute()
    {
        using (var scope = kernel.BeginScope())
        {
            // use your way to work with factories ;-)
            using (var myService = myServiceFactory.Create())
            {
                myService.DoWork();
            }
            // BTW: we have an extension method
            myServiceFactory.ExecuteAction(service =&amp;gt; service.DoWork());
        }
    }
}

…třída MyService class má všechny dependencies, které potřebuje a při použítí přes factory tím získáte nový pseudo-resolution-root. Svádí to samozřejmě použít rovnou kernel.Resolve+Release, ale nedělejte to… ;-)

References

Connect(); 2017 – přehled oznámených novinek

Od 15. do 17. listopadu proběhla online vývojářská konference Microsoft Connect(); 2017, která přinesla řadu zásadních oznámení a novinek. Pro základní orientaci přináším přehled těch nejdůležitějších. Záznamy jednotlivých session si můžete stále přehrát.

Visual Studio & Developer Productivity

https://blogs.msdn.microsoft.com/visualstudio/2017/11/15/the-latest-in-developer-productivity-and-app-experiences/

Team Foundation Server / Visual Studio Team Services

https://blogs.msdn.microsoft.com/bharry/2017/11/15/connect-announcements/

  • Team Foundation Server 2018 – final release. Přináší pro on-premise funkčnost, kterou již známe z onlinového VSTS:
    • Mobile work item experience – responsivní podoba TFS webu
    • Wiki – jednoduchá Wiki založená na GIT-repository s Markdown soubory (ála GitHub)
    • Git Forks – forking ála GitHub
    • GVFS – viz dále
    • Graphical release definition editor
    • Deployment groups
  • GVFS – Git Virtual File System – umožní efektivní práci s obrovskými repository (ála Windows source codes), kdy jsou na pracovní stanici staženy pouze minimální potřebné soubory a zbytek zůstává „virtuální“ a je stahován dle potřeby
  • Azure DevOps Projects – zjednodušeně řečeno onboarding wizzard pro Azure a VSTS, který pro různé typy projektů (.NET, Java, Node.js, Python, …) založí šablonu aplikace, GIT repo, CI/CD pipeline, atd.
  • YAML – Pipeline as code (public preview) – podpora YAML pro VSTS buildy – víceméně textová podoba vytváření build definic do VSTS.
  • Release management gates – možnost vytváření podmínek pro posun release do dalšího deployment prostředí, např. „žádné nové bugy“ (obecně libovolné Work Item Query), stav Azure Monitoru, či dle výsledku volání libovolného REST API či Azure Function.
  • VSTS Symbol Server (public preview)  – TFS (resp. zatím VSTS) se konečně stává symbol-serverem pro uchovávání a publikování PDB souborů. S každým buildem lze PDB symboly uchovat a následně je získávat do Visual Studia, Windows Debuggeru či jakoukoliv další potřebu.
  • Hosted MacOS Build Agents – ve VSTS se objevila možnost poslat build na Hosted MacOS agenta. Mimochodem je tam nově i Hosted Linux.
  • TFS data import service (general availability) – finální release služby pro import on-premise databáze TFS do online VSTS
  • VSTS CLI (public preview) – command-line tools pro VSTS a TFS, git-like commands, atp.

Data

  • Microsoft SQL Operations Studio (Preview) – odlehčená multiplatformní podoba SQL Server Management Studia
  • Azure Databricks (Preview) – Apache-Spark jako služba na Azure
  • Apache Cassandra API for Azure Cosmos DB (Preview) – jako další možnost připojení na Cosmos DB přibylo API dle Apache Cassandra.
  • Microsoft is joining the MariaDB Foundation – MariaDB – fork MySQL od jejího původního autora, získává podporu Microsoftu coby platinum sponzora tohoto open-source projektu. (Mimochodem věděli jste, že se obě tyto databáze vlastně jmenují po dceři jejich autora? MySQL není „moje“, ale švédská Maruška.)

Xamarin

https://blog.xamarin.com/xamarin-announcements-microsoft-connect-2017/

  • .NET Embedding
  • Xamarin.Forms 2.5
    • Xamarin.Forms Native Forms
    • Xamarin.Forms Layout Compression
    • Xamarin.Forms & XAML Standard
  • Xamarin Live Player
  • Xamarin Workbooks open-sourced

AI – Artificial Intelligence

Zaznělo mnoho dalších drobností a náznaků, spousta produktů releasovalo drobnější updates. Směřující myšlenky se točily rozhodně kolem AI.

Quartz .NET – sekvenční zřetězení jobů [Martin Havel, HAVIT Vzdělávací okénko 2.11.2017]

Záznam z interního vzdělávacího okénka HAVIT z 2.11.2017 je publikován na našem HAVIT YouTube Channel. Téma prezentoval Martin Havel:

Dotčená témata:

  • Co je Quartz
  • Sekvenční spouštění úloh
  • Tři způsoby, jak se zřetězením jobů vypořádat

 

Pattern matching – od C# k F# – záznam [Martin Havel, HAVIT Vzdělávací okénko 5.10.2017]

Záznam z interního vzdělávacího okénka HAVIT z 5.10.2017 je publikován na našem HAVIT YouTube Channel. Téma prezentoval Martin Havel:

Dotčená témata:

  • funkcionální programování
  • geneze projektu kalkulačky v F#

Mockování ConfigurationSection (nebo celého configu)

Při unit-testování se někdy ocitnete v situaci, kdy potřebujete namockovat ConfigurationSection, resp. svého potomka. Konfigurace jsou v .NET ale celkem zapouzdřené a není úplně jednoduché překonat jejich výchozí read-only pojetí.

Nejlepší by samozřejmě bylo se od frameworkovin abstrahovat a na konfigurační data přistupovat přes nějaký adaptér, někdy ale prostě nemůžete být 100% pure (třeba musíte ConfigSection někomu dál předat), a přesto chcete nějaké pokrytí testy.

Existuje obskurní, nicméně funkční, cest, jak ConfigurationSection namockovat (případně celý konfigurační soubor, pokud je potřeba):

1. Vytvořte fake konfigurační soubor(y) ve svém testovacím projektu

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<configSections>
<section name="mySection" type="MyConfigurationSection, MyAssembly" />
	</configSections>
	<mySection>
		<identities>
			<identity clientId="fake_id" name="FAKE_NAME" partitionName="FAKE_PARTITION" permissions="Full" />
		</identities>
	</mySection>
</configuration>

Soubor může být v jakékoliv složce, nejspíš přímo vedle třídy unit-testů.

2. Nastavte, aby se .config kopíroval do výstupu buildu

V Properties souboru nastavte:

  • Build Action = Content
  • Copy to Output Directory = Copy always

3. Vytvořte unit-test, který tento .config souboru použije pro vytoužený fake

[TestClass]
public class MyServiceTests
{
	public TestContext TestContext { get; set; }

	[TestMethod]
	[DeploymentItem("PathInTestProject\\MyServiceTests_ScenarioName.config")]
	public void MyService_DoSomething_ScenarioName_ExpectedBehavior()
	{
		// arrange
		ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap()
		{
			ExeConfigFilename = Path.Combine(TestContext.DeploymentDirectory, "MyServiceTests_ScenarioName.config")
		};
		Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
		MyConfiguarionSection mySection = config.GetSection("mySection") as MyConfiguarionSection ;

		var sut = new MyService(mySection);

		// act
		...
	}
}

V čem to spočívá:

  • Metoda ConfigurationManager.OpenMappedExeConfiguration() vás nechá načíst konfiguraci z libovolného souboru.
  • Atribut [DeploymentItem(...)] zařídí zkopírování souboru z výstupní složky buildu do „test deployment directory“ (např. $(SolutionDir)\TestResults\Deploy_username 2017-09-29 22_02_39\Out\)
  • Přes TestContext.DeploymentDirectory se dostanete na aktuální cestu složky, přičemž do TestContext property se vám automaticky nainjectuje testovací kontext.

WCF: The message with Action “ cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher.

Pokud voláte WCF webovou službu (SOAP) a dostáváte tuto response

The message with Action “ cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

…může to být kromě obvyklých zřejmých důvodů způsobeno i zcela chybějící HTTP-hlavičkou SOAPAction v příchozím HTTP-POST SOAP requestu (match je potom možný pouze na *-wildcard-action, cokoliv jiného končí chybou výše).