* Simple reflection example to obtain type information:
```csharp
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);
```
* 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:
```csharp
[Conditional("DEBUG")]
[Conditional("TEST1")]
void TraceMethod()
{
// ...
}
```
```csharp
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
// ...
}
```
### 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
* Traditionally, when new objects of classes are instantiated, the consuming class handles the creation of the objects
* Many classes change their functionality throughout the development of any project
* This means that also _every single_ consuming class has to change
* This is called *__tight coupling__*
### The solution
* What if, instead of directly creating the objects, they were provided by some interface that takes care of the creation?
* This way, even if the base class changes, the consuming classes won't care because they only know about the provider
* This provider is called *__Container__*, and the functionality being injected is called *__Service__*
* In ASP.NET, this container system is built in
### Dependency injection in ASP.NET
```csharp
public class HomeController : Controller
{
private readonly IUserRepository _userRepository;
public HomeController(IUserRepository userRepository)
{
_userRepository = userRepository;
}
// User repository including all users is now accessible in HomeController
}
```
## Design Patterns
* If the concepts of a singleton and dependency injection flew over your head, don't worry about it
* The important thing is to know they exist so that when they come up again in ASP.NET, you have already familiarized yourself with the terms
* Thus, understanding the logic behind ASP.NET becomes less overwhelming
* There are many more design patterns, see the material [here](https://www.c-sharpcorner.com/UploadFile/bd5be5/design-patterns-in-net/)
```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton
();
services.AddControllersWithViews();
}
```