add reflection and attributes

main
borb 5 days ago
parent ed446e85b3
commit a4274969bb

@ -13,20 +13,21 @@
/* buutti.css */
/* @theme buutti */div#\:\$p>svg>foreignObject>section .columns{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns12{display:grid;grid-template-columns:1fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns21{display:grid;grid-template-columns:2fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns32{display:grid;grid-template-columns:3fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns23{display:grid;grid-template-columns:2fr 3fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .columns111{display:grid;grid-template-columns:1fr 1fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 1)}div#\:\$p>svg>foreignObject>section .centered{display:flex;flex-direction:column;justify-content:center;text-align:center}div#\:\$p>svg>foreignObject>section .tableborderless td,div#\:\$p>svg>foreignObject>section th{border:none!important;border-collapse:collapse}div#\:\$p>svg>foreignObject>section.extra{background-color:#5d275d;background-image:linear-gradient(to bottom,#401a40,#1d0c1d);color:white}div#\:\$p>svg>foreignObject>section.extra a{color:rgb(145,255,209)}div#\:\$p>svg>foreignObject>section.exercise{background-color:#29366f;background-image:linear-gradient(to bottom,#20636a,#173742);color:white}div#\:\$p>svg>foreignObject>section.exercise a{color:rgb(211,173,255)}
/* @theme 1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95 */div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}</style></head><body><div class="bespoke-marp-osc"><button data-bespoke-marp-osc="prev" tabindex="-1" title="Previous slide">Previous slide</button><span data-bespoke-marp-osc="page"></span><button data-bespoke-marp-osc="next" tabindex="-1" title="Next slide">Next slide</button><button data-bespoke-marp-osc="fullscreen" tabindex="-1" title="Toggle fullscreen (f)">Toggle fullscreen</button><button data-bespoke-marp-osc="presenter" tabindex="-1" title="Open presenter view (p)">Open presenter view</button></div><div id=":$p"><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="1" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="1" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
/* @theme l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn */div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]:before,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:after,div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content]:before{display:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction=vertical]{flex-direction:column}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split]>div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split,50%)}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background][data-marpit-advanced-background-split=right]>div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=background]>div[data-marpit-advanced-background-container]>figure>figcaption{position:absolute;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=content],div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo]{background:transparent!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background=pseudo],div#\:\$p>svg[data-marpit-svg]>foreignObject[data-marpit-advanced-background=pseudo]{pointer-events:none!important}div#\:\$p>svg>foreignObject>section[data-marpit-advanced-background-split]{width:100%;height:100%}</style></head><body><div class="bespoke-marp-osc"><button data-bespoke-marp-osc="prev" tabindex="-1" title="Previous slide">Previous slide</button><span data-bespoke-marp-osc="page"></span><button data-bespoke-marp-osc="next" tabindex="-1" title="Next slide">Next slide</button><button data-bespoke-marp-osc="fullscreen" tabindex="-1" title="Toggle fullscreen (f)">Toggle fullscreen</button><button data-bespoke-marp-osc="presenter" tabindex="-1" title="Open presenter view (p)">Open presenter view</button></div><div id=":$p"><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="1" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="1" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h1 id="design-patterns-in-c">Design Patterns in C#</h1>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="2" data-marpit-fragments="2" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="2" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="2" data-marpit-fragments="3" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="2" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h2 id="overview">Overview</h2>
<ul>
<li data-marpit-fragment="1">The Singleton Pattern</li>
<li data-marpit-fragment="2">Dependency Injection</li>
<li data-marpit-fragment="2">Reflection and attributes</li>
<li data-marpit-fragment="3">Dependency Injection</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="3" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="3" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="3" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="3" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h2 id="the-singleton-pattern">The Singleton Pattern</h2>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="4" data-marpit-fragments="7" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="4" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="4" data-marpit-fragments="7" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="4" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h3 id="the-problem">The problem</h3>
<ul>
<li data-marpit-fragment="1">In most cases, it makes no sense to create an instance of a class every time its members need to be accessed
@ -44,7 +45,7 @@
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="5" data-marpit-fragments="4" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="5" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="5" data-marpit-fragments="4" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="5" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h3 id="the-solution">The solution</h3>
<ul>
<li data-marpit-fragment="1">The <strong>singleton</strong> class is a class that benefits from all the perks of a non-static class (non-static members, inheritance, referencing…), but only one (or zero) instances of it ever exists during the lifetime of your application</li>
@ -56,7 +57,7 @@
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="6" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="6" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="6" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="6" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<p>A singleton implementation could look something like this:</p>
<div class='columns' markdown='1'>
<div markdown='1'>
@ -97,17 +98,126 @@
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="7" data-marpit-fragments="2" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="7" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="7" data-marpit-fragments="2" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="7" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h3 id="implementing-a-singleton-pattern">Implementing a singleton pattern</h3>
<ul>
<li data-marpit-fragment="1">The exact implementation of the singleton is out of the scope of this course, but it is important to understand that it exists and what its purpose is</li>
<li data-marpit-fragment="2">Multitude of examples for different use cases are available and can be found by googling</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="8" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="8" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="8" data-marpit-fragments="4" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="8" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h2 id="reflection">Reflection</h2>
<ul>
<li data-marpit-fragment="1">Reflective programming or reflection is the ability for the program to examine or modify its own structure and behaviour</li>
<li data-marpit-fragment="2">C# has special reflection methods that we can use to get information about types</li>
</ul>
<div class='columns' markdown='1'>
<div markdown='1'>
<ul>
<li data-marpit-fragment="3">Simple reflection example to obtain type information:<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-csharp"><span class="hljs-built_in">int</span> i = <span class="hljs-number">42</span>;
Type type = i.GetType();
Console.WriteLine(type);
</code></pre>
</li>
</ul>
</div>
<div markdown='1'>
<ul>
<li data-marpit-fragment="4">Use strings to invoke methods:<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-csharp"><span class="hljs-comment">// Without reflection</span>
<span class="hljs-keyword">var</span> foo = <span class="hljs-keyword">new</span> Foo();
foo.PrintHello();
<span class="hljs-comment">// With reflection</span>
Object foo = Activator.CreateInstance
(<span class="hljs-string">&quot;complete.classpath.and.Foo&quot;</span>);
MethodInfo method = foo
.GetType()
.GetMethod(<span class="hljs-string">&quot;PrintHello&quot;</span>);
method.Invoke(foo, <span class="hljs-literal">null</span>);
</code></pre>
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="9" data-marpit-fragments="5" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="9" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h3 id="attributes">Attributes</h3>
<ul>
<li data-marpit-fragment="1"><a href="https://learn.microsoft.com/en-us/dotnet/standard/attributes/">Attributes</a> can be used to extend methods, classes, or even entire programs with new <em><strong>metadata</strong></em>
<ul>
<li data-marpit-fragment="2">Metadata is information about the types defined</li>
</ul>
</li>
<li data-marpit-fragment="3">Attributes use reflection so the program can examine its own metadata</li>
<li data-marpit-fragment="4">Here's an example of the built-in <a href="https://learn.microsoft.com/en-us/dotnet/api/system.serializableattribute?view=net-9.0">SerializableAttribute</a>.</li>
<li data-marpit-fragment="5">Attribute is used by placing its name in square brackets <code>[]</code> above the declaration of the entity you want it to apply to<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-csharp">[<span class="hljs-meta">Serializable</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">SampleClass</span>
{
<span class="hljs-comment">// Objects of this type can be serialized.</span>
}
</code></pre>
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="10" data-marpit-fragments="2" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="10" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<ul>
<li data-marpit-fragment="1">
<p>Attributes can also have parameters:</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-csharp">[<span class="hljs-meta">Obsolete(<span class="hljs-string">&quot;Will be removed in next version.&quot;</span>)</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-built_in">int</span> <span class="hljs-title">Add</span>(<span class="hljs-params"><span class="hljs-built_in">int</span> a, <span class="hljs-built_in">int</span> b</span>)</span>
{
<span class="hljs-keyword">return</span> (a + b);
}
</code></pre>
</li>
<li data-marpit-fragment="2">
<p>You can add multiple attributes either on separate lines or by separating them with a comma:</p>
</li>
</ul>
<div class='columns' markdown='1'>
<div markdown='1'>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-csharp">[<span class="hljs-meta">Conditional(<span class="hljs-string">&quot;DEBUG&quot;</span>)</span>]
[<span class="hljs-meta">Conditional(<span class="hljs-string">&quot;TEST1&quot;</span>)</span>]
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">TraceMethod</span>()</span>
{
<span class="hljs-comment">// ...</span>
}
</code></pre>
</div>
<div markdown='1'>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-csharp">[<span class="hljs-meta">Conditional(<span class="hljs-string">&quot;DEBUG&quot;</span>), Conditional(<span class="hljs-string">&quot;TEST1&quot;</span>)</span>]
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">TraceMethod</span>()</span>
{
<span class="hljs-comment">// ...</span>
}
</code></pre>
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="11" data-marpit-fragments="2" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="11" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h3 id="custom-attributes">Custom attributes</h3>
<ul>
<li data-marpit-fragment="1">You can write your own <a href="https://learn.microsoft.com/en-us/dotnet/standard/attributes/writing-custom-attributes">custom attributes</a> by inheriting from the <code>Attribute</code> class<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-csharp"><span class="hljs-comment">// This defaults to Inherited = true.</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyAttribute</span> : <span class="hljs-title">Attribute</span>
{
<span class="hljs-comment">//...</span>
}
</code></pre>
</li>
<li data-marpit-fragment="2">Then, you can use it like any other attribute<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>
{
[<span class="hljs-meta">MyAttribute</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">MyMethod</span>()</span>
{
<span class="hljs-comment">//...</span>
}
}
</code></pre>
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="12" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="12" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h2 id="dependency-injection">Dependency Injection</h2>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="9" data-marpit-fragments="4" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="9" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="13" data-marpit-fragments="4" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="13" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h3 id="the-problem-1">The problem</h3>
<ul>
<li data-marpit-fragment="1">Traditionally, when new objects of classes are instantiated, the consuming class handles the creation of the objects</li>
@ -119,7 +229,7 @@
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="10" data-marpit-fragments="4" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="10" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="14" data-marpit-fragments="4" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="14" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h3 id="the-solution-1">The solution</h3>
<ul>
<li data-marpit-fragment="1">What if, instead of directly creating the objects, they were provided by some interface that takes care of the creation?</li>
@ -128,7 +238,7 @@
<li data-marpit-fragment="4">In ASP.NET, this container system is built in</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="11" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="11" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="15" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="15" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h3 id="dependency-injection-in-aspnet">Dependency injection in ASP.NET</h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">HomeController</span> : <span class="hljs-title">Controller</span>
{
@ -142,7 +252,7 @@
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="12" data-marpit-fragments="4" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95" lang="en-US" class="invert" data-marpit-pagination="12" style="--paginate:true;--class:invert;--heading-divider:5;--theme:1ysjiehhorul1p4de1exx6vqige0dfz5fvqkoxyrp95;" data-marpit-pagination-total="12">
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="16" data-marpit-fragments="4" data-paginate="true" data-class="invert" data-heading-divider="5" data-theme="l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn" lang="en-US" class="invert" data-marpit-pagination="16" style="--paginate:true;--class:invert;--heading-divider:5;--theme:l88lgdm6g50jnf1zbzajbvpkez0urw5hs65fwufujn;" data-marpit-pagination-total="16">
<h2 id="design-patterns">Design Patterns</h2>
<ul>
<li data-marpit-fragment="1">If the concepts of a singleton and dependency injection flew over your head, don't worry about it</li>

@ -14,6 +14,7 @@ title: 15. Design Patterns in C#
## Overview
* The Singleton Pattern
* Reflection and attributes
* Dependency Injection
## The Singleton Pattern
@ -82,12 +83,122 @@ class Program
</div>
</div>
### Implementing a singleton pattern
* The exact implementation of the singleton is out of the scope of this course, but it is important to understand that it exists and what its purpose is
* Multitude of examples for different use cases are available and can be found by googling
## Reflection
* Reflective programming or reflection is the ability for the program to examine or modify its own structure and behaviour
* C# has special reflection methods that we can use to get information about types
<div class='columns' markdown='1'>
<div markdown='1'>
* Simple reflection example to obtain type information:
```csharp
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);
```
</div>
<div markdown='1'>
* Use strings to invoke methods:
```csharp
// Without reflection
var foo = new Foo();
foo.PrintHello();
// With reflection
Object foo = Activator.CreateInstance
("complete.classpath.and.Foo");
MethodInfo method = foo
.GetType()
.GetMethod("PrintHello");
method.Invoke(foo, null);
```
### Attributes
* [Attributes](https://learn.microsoft.com/en-us/dotnet/standard/attributes/
) can be used to extend methods, classes, or even entire programs with new ***metadata***
* Metadata is information about the types defined
* Attributes use reflection so the program can examine its own metadata
* Here's an example of the built-in [SerializableAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.serializableattribute?view=net-9.0).
* Attribute is used by placing its name in square brackets `[]` above the declaration of the entity you want it to apply to
```csharp
[Serializable]
public class SampleClass
{
// Objects of this type can be serialized.
}
```
---
* Attributes can also have parameters:
```csharp
[Obsolete("Will be removed in next version.")]
public static int Add(int a, int b)
{
return (a + b);
}
```
* You can add multiple attributes either on separate lines or by separating them with a comma:
<div class='columns' markdown='1'>
<div markdown='1'>
```csharp
[Conditional("DEBUG")]
[Conditional("TEST1")]
void TraceMethod()
{
// ...
}
```
</div>
<div markdown='1'>
```csharp
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
// ...
}
```
</div>
</div>
### Custom attributes
* You can write your own [custom attributes](https://learn.microsoft.com/en-us/dotnet/standard/attributes/writing-custom-attributes) by inheriting from the `Attribute` class
```csharp
// This defaults to Inherited = true.
public class MyAttribute : Attribute
{
//...
}
```
* Then, you can use it like any other attribute
```csharp
public class MyClass
{
[MyAttribute]
public virtual void MyMethod()
{
//...
}
}
```
## Dependency Injection
### The problem

Loading…
Cancel
Save