Ver3.0 ๐ญ C# ๋ฆฌํ๋ ์ ๊ณผ ๋์ ํ๋ก๊ทธ๋๋ฐ ๋ฉํ๋ฐ์ดํฐ ํ์ฉ ๊ธฐ๋ฒ

๐ญ C# ๋ฆฌํ๋ ์ ๊ณผ ๋์ ํ๋ก๊ทธ๋๋ฐ ๋ฉํ๋ฐ์ดํฐ ํ์ฉ ๊ธฐ๋ฒ
๋ฐํ์์ ์ฝ๋๋ฅผ ๋ค์ฌ๋ค๋ณด๊ณ ์กฐ์ํ๋ ๋ง๋ฒ ๊ฐ์ ๊ธฐ์ ! ๐ฎโจ
๐ ๋ฆฌํ๋ ์ , ์ด๊ฒ ๋ญ๋ฐ ์ด๋ ๊ฒ ์ ๊ธฐํด?
์น๊ตฌ์ผ, ํ๋ก๊ทธ๋จ์ด ์คํ๋๋ ๋์ ์๊ธฐ ์์ ์ ์ฝ๋๋ฅผ ๋ค์ฌ๋ค๋ณผ ์ ์๋ค๋ฉด ์ด๋จ๊น? ๐ค
๋ง์น ๊ฑฐ์ธ์ ๋ณด๋ฏ์ด ์์ ์ ๊ตฌ์กฐ๋ฅผ ํ์
ํ๊ณ , ์ฌ์ง์ด ๊ทธ๊ฑธ ๋ฐ๊ฟ ์๋ ์๋ค๋ฉด?
๋ฐ๋ก ๊ทธ๊ฒ ๋ฆฌํ๋ ์
(Reflection)์ด์ผ!
C#์์ ๋ฆฌํ๋ ์
์ ํ๋ก๊ทธ๋จ์ด ์คํ ์ค์ ์์ ์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ฌํ๊ณ ์กฐ์ํ ์ ์๊ฒ ํด์ฃผ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ด์ผ.
์ฝ๊ฒ ๋งํ๋ฉด, ์ฝ๋๊ฐ ์ฝ๋๋ฅผ ์ฝ๊ณ ๋ถ์ํ๋ ๊ฑฐ์ง. ๐
์ปดํ์ผ ํ์์๋ ๋ชฐ๋๋ ํ์
์ ๋ณด๋ฅผ ๋ฐํ์์ ์์๋ผ ์ ์๊ณ ,
์ฌ์ง์ด ๋์ ์ผ๋ก ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฑฐ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์๋ ์์ด!
โข ํ๋ฌ๊ทธ์ธ ์์คํ ๊ตฌ์ถํ ๋ (์ธ๋ถ DLL์ ๋์ ์ผ๋ก ๋ก๋)
โข ORM(Object-Relational Mapping) ํ๋ ์์ํฌ ๊ฐ๋ฐ
โข ์ง๋ ฌํ/์ญ์ง๋ ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ง๋ค ๋
โข ์์กด์ฑ ์ฃผ์ (DI) ์ปจํ ์ด๋ ๊ตฌํ
โข ํ ์คํธ ํ๋ ์์ํฌ๋ ๋ชฉ(Mock) ๊ฐ์ฒด ์์ฑ
โข ๋ฐํ์์ ํ์ ์ ๋ณด๋ฅผ ์์์ผ ํ๋ ๋ชจ๋ ์ํฉ! ๐ฏ
๐ ๋ฉํ๋ฐ์ดํฐ๋ ๋ฌด์์ธ๊ฐ?
๋ฉํ๋ฐ์ดํฐ๋ "๋ฐ์ดํฐ์ ๋ํ ๋ฐ์ดํฐ"์ผ. ๐ช
C#์์๋ ์ด์
๋ธ๋ฆฌ(Assembly)์ ํฌํจ๋ ํ์
, ๋ฉ์๋, ํ๋กํผํฐ, ์ดํธ๋ฆฌ๋ทฐํธ ๋ฑ์ ์ ๋ณด๋ฅผ ๋งํด.
์ปดํ์ผ๋ฌ๊ฐ ์ฝ๋๋ฅผ ์ปดํ์ผํ ๋ ์ด ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก ์์ฑํด์ ์ด์
๋ธ๋ฆฌ์ ํจ๊ป ์ ์ฅํ์ง.
์๋ฅผ ๋ค์ด, ๋๊ฐ class Person์ด๋ผ๋ ํด๋์ค๋ฅผ ๋ง๋ค๋ฉด,
์ปดํ์ผ๋ฌ๋ "Person์ด๋ผ๋ ํด๋์ค๊ฐ ์๊ณ , ์ด ํด๋์ค์๋ Name์ด๋ผ๋ ํ๋กํผํฐ๊ฐ ์๊ณ ,
GetAge()๋ผ๋ ๋ฉ์๋๊ฐ ์๋ค"๋ ์ ๋ณด๋ฅผ ๋ฉํ๋ฐ์ดํฐ๋ก ์ ์ฅํด.
๋ฆฌํ๋ ์
์ ๋ฐ๋ก ์ด ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ ํ์ฉํ๋ ๊ฑฐ์ผ! ๐
โข ํ์ ์ด๋ฆ๊ณผ ๋ค์์คํ์ด์ค
โข ์์ ๊ด๊ณ ๋ฐ ๊ตฌํ๋ ์ธํฐํ์ด์ค
โข ๋ฉค๋ฒ ์ ๋ณด (ํ๋, ํ๋กํผํฐ, ๋ฉ์๋, ์ด๋ฒคํธ)
โข ์ ๊ทผ ์ ํ์ (public, private ๋ฑ)
โข ์ปค์คํ ์ดํธ๋ฆฌ๋ทฐํธ
โข ์ ๋ค๋ฆญ ํ์ ๋งค๊ฐ๋ณ์
โข ์ด์ ๋ธ๋ฆฌ ๋ฒ์ ๋ฐ ์ฐธ์กฐ ์ ๋ณด
โ๏ธ System.Reflection ๋ค์์คํ์ด์ค ํํค์น๊ธฐ
C#์์ ๋ฆฌํ๋ ์
์ ์ฌ์ฉํ๋ ค๋ฉด System.Reflection ๋ค์์คํ์ด์ค๋ฅผ ์์์ผ ํด.
์ฌ๊ธฐ์๋ ๋ฆฌํ๋ ์
์์
์ ํ์ํ ํต์ฌ ํด๋์ค๋ค์ด ๋ชจ์ฌ ์์ด! ๐ ๏ธ
| ํด๋์ค | ์ญํ | ์ฃผ์ ์ฉ๋ |
|---|---|---|
| Type | ํ์ ์ ๋ณด ํํ | ํด๋์ค, ์ธํฐํ์ด์ค, ๊ตฌ์กฐ์ฒด ๋ฑ์ ํ์ ์ ๋ณด ์กฐํ |
| Assembly | ์ด์ ๋ธ๋ฆฌ ํํ | DLL/EXE ๋ก๋, ํ์ ๊ฒ์ |
| MethodInfo | ๋ฉ์๋ ์ ๋ณด | ๋ฉ์๋ ์๊ทธ๋์ฒ, ๋์ ํธ์ถ |
| PropertyInfo | ํ๋กํผํฐ ์ ๋ณด | ํ๋กํผํฐ ๊ฐ ์ฝ๊ธฐ/์ฐ๊ธฐ |
| FieldInfo | ํ๋ ์ ๋ณด | ํ๋ ๊ฐ ์ ๊ทผ ๋ฐ ์์ |
| ConstructorInfo | ์์ฑ์ ์ ๋ณด | ๋์ ๊ฐ์ฒด ์์ฑ |
| EventInfo | ์ด๋ฒคํธ ์ ๋ณด | ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ถ๊ฐ/์ ๊ฑฐ |
๐ป ๊ธฐ๋ณธ ๋ฆฌํ๋ ์ ์ฌ์ฉ๋ฒ - Type ๊ฐ์ฒด ์ป๊ธฐ
๋ฆฌํ๋ ์
์ ์์์ Type ๊ฐ์ฒด๋ฅผ ์ป๋ ๊ฒ๋ถํฐ์ผ! ๐ฌ
Type ๊ฐ์ฒด๋ฅผ ์ป๋ ๋ฐฉ๋ฒ์ ํฌ๊ฒ ์ธ ๊ฐ์ง๊ฐ ์์ด:
1๏ธโฃ typeof ์ฐ์ฐ์ ์ฌ์ฉ (์ปดํ์ผ ํ์์ ํ์ ์ ์ ๋)
Type type1 = typeof(string);
Type type2 = typeof(List<int>);
Type type3 = typeof(MyCustomClass);
Console.WriteLine(type1.Name); // String
Console.WriteLine(type1.FullName); // System.String
Console.WriteLine(type1.Namespace); // System
2๏ธโฃ GetType() ๋ฉ์๋ ์ฌ์ฉ (๊ฐ์ฒด ์ธ์คํด์ค๊ฐ ์์ ๋)
string text = "Hello, Reflection!";
Type type = text.GetType();
int number = 42;
Type numType = number.GetType();
Console.WriteLine(type.Name); // String
Console.WriteLine(numType.Name); // Int32
3๏ธโฃ Type.GetType() ๋ฉ์๋ ์ฌ์ฉ (๋ฌธ์์ด๋ก ํ์ ์ด๋ฆ์ ์ ๋)
// ์ ๊ทํ๋ ํ์
์ด๋ฆ ์ฌ์ฉ
Type type1 = Type.GetType("System.String");
Type type2 = Type.GetType("System.Collections.Generic.List`1");
// ๊ฐ์ ์ด์
๋ธ๋ฆฌ ๋ด์ ํ์
Type type3 = Type.GetType("MyNamespace.MyClass");
if (type1 != null)
{
Console.WriteLine($"ํ์
์ ์ฐพ์์ด์: {type1.FullName}");
}
Type.GetType()์ ํ์ ์ ์ฐพ์ง ๋ชปํ๋ฉด null์ ๋ฐํํด.
๋ค๋ฅธ ์ด์ ๋ธ๋ฆฌ์ ํ์ ์ ์ฐพ์ผ๋ ค๋ฉด ์ด์ ๋ธ๋ฆฌ ์ ๊ทํ๋ ์ด๋ฆ์ ์ฌ์ฉํด์ผ ํด!
์: "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
๐ ํ์ ์ ๋ณด ํ์ํ๊ธฐ
Type ๊ฐ์ฒด๋ฅผ ์ป์๋ค๋ฉด, ์ด์ ๊ทธ ํ์
์ ๋ํ ์จ๊ฐ ์ ๋ณด๋ฅผ ์บ๋ผ ์ ์์ด! ๐ต๏ธ
์ค์ ๋ก ์ฌ์ฉํ ์ ์๋ ์์ ๋ฅผ ํ๋ฒ ๋ณผ๊น?
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
private string _secret = "๋น๋ฐ์ด์ผ!";
public Person() { }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public void SayHello()
{
Console.WriteLine($"์๋
! ๋๋ {Name}์ด์ผ!");
}
private void SecretMethod()
{
Console.WriteLine("์ด๊ฑด ๋น๋ฐ ๋ฉ์๋!");
}
}
// ๋ฆฌํ๋ ์
์ผ๋ก Person ํด๋์ค ๋ถ์ํ๊ธฐ
Type personType = typeof(Person);
Console.WriteLine($"๐ ํ์
์ด๋ฆ: {personType.Name}");
Console.WriteLine($"๐ ์ ์ฒด ์ด๋ฆ: {personType.FullName}");
Console.WriteLine($"๐ ๋ค์์คํ์ด์ค: {personType.Namespace}");
Console.WriteLine($"๐ ํด๋์ค์ธ๊ฐ? {personType.IsClass}");
Console.WriteLine($"๐ ์ถ์ ํด๋์ค์ธ๊ฐ? {personType.IsAbstract}");
Console.WriteLine($"๐ ๋ด์ธ(sealed)๋์๋? {personType.IsSealed}");
// ํ๋กํผํฐ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
Console.WriteLine("\n๐ ํ๋กํผํฐ ๋ชฉ๋ก:");
PropertyInfo[] properties = personType.GetProperties();
foreach (var prop in properties)
{
Console.WriteLine($" - {prop.Name} ({prop.PropertyType.Name})");
Console.WriteLine($" ์ฝ๊ธฐ ๊ฐ๋ฅ: {prop.CanRead}, ์ฐ๊ธฐ ๊ฐ๋ฅ: {prop.CanWrite}");
}
// ๋ฉ์๋ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
Console.WriteLine("\n๐ ๋ฉ์๋ ๋ชฉ๋ก:");
MethodInfo[] methods = personType.GetMethods(
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
foreach (var method in methods)
{
Console.WriteLine($" - {method.Name}");
Console.WriteLine($" ๋ฐํ ํ์
: {method.ReturnType.Name}");
ParameterInfo[] parameters = method.GetParameters();
if (parameters.Length > 0)
{
Console.WriteLine(" ๋งค๊ฐ๋ณ์:");
foreach (var param in parameters)
{
Console.WriteLine($" โข {param.Name} ({param.ParameterType.Name})");
}
}
}
// ์์ฑ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
Console.WriteLine("\n๐ ์์ฑ์ ๋ชฉ๋ก:");
ConstructorInfo[] constructors = personType.GetConstructors();
foreach (var ctor in constructors)
{
ParameterInfo[] parameters = ctor.GetParameters();
Console.WriteLine($" - ๋งค๊ฐ๋ณ์ ๊ฐ์: {parameters.Length}");
foreach (var param in parameters)
{
Console.WriteLine($" โข {param.Name} ({param.ParameterType.Name})");
}
}
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด Person ํด๋์ค์ ๋ชจ๋ ๊ตฌ์กฐ๋ฅผ ๋ฐํ์์ ํ์
ํ ์ ์์ด! ๐ฒ
๋ง์น X-ray๋ก ํด๋์ค ๋ด๋ถ๋ฅผ ๋ค์ฌ๋ค๋ณด๋ ๊ฒ ๊ฐ์ง?
๐ฏ BindingFlags - ๊ฒ์ ๋ฒ์ ์ง์ ํ๊ธฐ
๋ฆฌํ๋ ์
์ผ๋ก ๋ฉค๋ฒ๋ฅผ ๊ฒ์ํ ๋ BindingFlags๋ฅผ ์ฌ์ฉํ๋ฉด
์ด๋ค ๋ฉค๋ฒ๋ฅผ ์ฐพ์์ง ์ธ๋ฐํ๊ฒ ์ ์ดํ ์ ์์ด! ๐๏ธ
์ ๊ทผ์ฑ ๊ด๋ จ:
โข Public - public ๋ฉค๋ฒ๋ง
โข NonPublic - private, protected, internal ๋ฉค๋ฒ
๋ฉค๋ฒ ์ข ๋ฅ:
โข Instance - ์ธ์คํด์ค ๋ฉค๋ฒ
โข Static - ์ ์ (static) ๋ฉค๋ฒ
์์ ๊ด๋ จ:
โข DeclaredOnly - ํด๋น ํ์ ์์ ์ง์ ์ ์ธ๋ ๋ฉค๋ฒ๋ง (์์๋ ๋ฉค๋ฒ ์ ์ธ)
โข FlattenHierarchy - ์์ ๊ณ์ธต ์ ์ฒด์์ ์ ์ ๋ฉค๋ฒ ํฌํจ
๊ธฐํ:
โข IgnoreCase - ๋์๋ฌธ์ ๊ตฌ๋ถ ์ ํจ
โข CreateInstance - ์ธ์คํด์ค ์์ฑ ์ ์ฌ์ฉ
Type type = typeof(Person);
// public ์ธ์คํด์ค ๋ฉค๋ฒ๋ง
var publicMembers = type.GetMembers(BindingFlags.Public | BindingFlags.Instance);
// private ์ธ์คํด์ค ํ๋๋ง
var privateFields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
// ๋ชจ๋ ๋ฉ์๋ (public + private, instance + static)
var allMethods = type.GetMethods(
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static);
// ํน์ ์ด๋ฆ์ ๋ฉ์๋ ์ฐพ๊ธฐ (๋์๋ฌธ์ ๋ฌด์)
var method = type.GetMethod("sayhello",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
Console.WriteLine($"์ฐพ์ ๋ฉ์๋: {method?.Name}");
๐ ๋์ ์ผ๋ก ๊ฐ์ฒด ์์ฑํ๊ธฐ
๋ฆฌํ๋ ์
์ ์ง์ง ๋งค๋ ฅ์ ๋ฐํ์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ค๋ ๊ฑฐ์ผ! ๐จ
์ปดํ์ผ ํ์์๋ ์ด๋ค ํ์
์ธ์ง ๋ชฐ๋ผ๋, ์คํ ์ค์ ๋์ ์ผ๋ก ์ธ์คํด์ค๋ฅผ ๋ง๋ค ์ ์์ง.
๋ฐฉ๋ฒ 1: Activator.CreateInstance ์ฌ์ฉ (๊ฐ์ฅ ๊ฐ๋จ)
// ๊ธฐ๋ณธ ์์ฑ์๋ก ๊ฐ์ฒด ์์ฑ
Type type = typeof(Person);
object instance = Activator.CreateInstance(type);
// ์ ๋ค๋ฆญ ๋ฒ์ (ํ์
์บ์คํ
๋ถํ์)
Person person = Activator.CreateInstance<Person>();
// ๋งค๊ฐ๋ณ์๊ฐ ์๋ ์์ฑ์ ์ฌ์ฉ
object instance2 = Activator.CreateInstance(type, "ํ๊ธธ๋", 25);
Person person2 = (Person)instance2;
person2.SayHello(); // "์๋
! ๋๋ ํ๊ธธ๋์ด์ผ!"
๋ฐฉ๋ฒ 2: ConstructorInfo ์ฌ์ฉ (๋ ์ธ๋ฐํ ์ ์ด)
Type type = typeof(Person);
// ํน์ ์์ฑ์ ์ฐพ๊ธฐ
ConstructorInfo constructor = type.GetConstructor(
new Type[] { typeof(string), typeof(int) });
if (constructor != null)
{
// ์์ฑ์ ํธ์ถ
object instance = constructor.Invoke(new object[] { "์ด์์ ", 30 });
Person person = (Person)instance;
person.SayHello(); // "์๋
! ๋๋ ์ด์์ ์ด์ผ!"
}
// ๊ธฐ๋ณธ ์์ฑ์ ์ฐพ๊ธฐ
ConstructorInfo defaultCtor = type.GetConstructor(Type.EmptyTypes);
object instance2 = defaultCtor?.Invoke(null);
๋ฐฉ๋ฒ 3: FormatterServices (๊ถ์ฅํ์ง ์์, ํน์ํ ๊ฒฝ์ฐ๋ง)
using System.Runtime.Serialization;
// ์์ฑ์๋ฅผ ํธ์ถํ์ง ์๊ณ ๊ฐ์ฒด ์์ฑ (์ด๊ธฐํ๋์ง ์์ ์ํ)
Type type = typeof(Person);
object instance = FormatterServices.GetUninitializedObject(type);
// ์ฃผ์: ์์ฑ์๊ฐ ์คํ๋์ง ์์ผ๋ฏ๋ก ํ๋๊ฐ ์ด๊ธฐํ๋์ง ์์!
// ์ง๋ ฌํ ํ๋ ์์ํฌ ๋ฑ ํน์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉ
๋ฆฌํ๋ ์ ์ผ๋ก ๊ฐ์ฒด๋ฅผ ์์ฃผ ์์ฑํด์ผ ํ๋ค๋ฉด, Activator.CreateInstance๋ณด๋ค
Delegate๋ Expression Tree๋ฅผ ์ฌ์ฉํด์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ฅผ ๋ง๋๋ ๊ฒ ํจ์ฌ ๋นจ๋ผ!
ํ ๋ฒ ๋ง๋ค์ด๋๋ฉด ์ผ๋ฐ ์์ฑ์ ํธ์ถ๊ณผ ๋น์ทํ ์๋๋ก ๋์ํด. ๐โโ๏ธ
๐ช ๋์ ์ผ๋ก ๋ฉ์๋ ํธ์ถํ๊ธฐ
๊ฐ์ฒด๋ฅผ ๋ง๋ค์์ผ๋ ์ด์ ๋ฉ์๋๋ฅผ ํธ์ถํด๋ณผ๊น? ๐
๋ฆฌํ๋ ์
์ ์ฌ์ฉํ๋ฉด ๋ฉ์๋ ์ด๋ฆ๋ง ์๋ฉด ๋์ ์ผ๋ก ์คํํ ์ ์์ด!
Person person = new Person("๊น์ฒ ์", 28);
Type type = person.GetType();
// ๋ฉ์๋ ์ฐพ๊ธฐ
MethodInfo method = type.GetMethod("SayHello");
if (method != null)
{
// ๋ฉ์๋ ํธ์ถ (๋งค๊ฐ๋ณ์ ์์)
method.Invoke(person, null);
// ์ถ๋ ฅ: "์๋
! ๋๋ ๊น์ฒ ์์ผ!"
}
// ๋งค๊ฐ๋ณ์๊ฐ ์๋ ๋ฉ์๋ ํธ์ถ ์์
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public double Multiply(double x, double y)
{
return x * y;
}
}
Calculator calc = new Calculator();
Type calcType = calc.GetType();
// Add ๋ฉ์๋ ํธ์ถ
MethodInfo addMethod = calcType.GetMethod("Add");
object result = addMethod.Invoke(calc, new object[] { 10, 20 });
Console.WriteLine($"10 + 20 = {result}"); // 30
// Multiply ๋ฉ์๋ ํธ์ถ
MethodInfo multiplyMethod = calcType.GetMethod("Multiply");
object result2 = multiplyMethod.Invoke(calc, new object[] { 3.5, 2.0 });
Console.WriteLine($"3.5 ร 2.0 = {result2}"); // 7.0
private ๋ฉ์๋๋ ํธ์ถํ ์ ์์ด! ๐
Type type = typeof(Person);
Person person = new Person("๋น๋ฐ์์", 35);
// private ๋ฉ์๋ ์ฐพ๊ธฐ
MethodInfo secretMethod = type.GetMethod("SecretMethod",
BindingFlags.NonPublic | BindingFlags.Instance);
if (secretMethod != null)
{
// private ๋ฉ์๋ ํธ์ถ!
secretMethod.Invoke(person, null);
// ์ถ๋ ฅ: "์ด๊ฑด ๋น๋ฐ ๋ฉ์๋!"
}
// ์ด๋ ๊ฒ ํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก๋ ์ ๊ทผํ ์ ์๋ private ๋ฉค๋ฒ์๋ ์ ๊ทผ ๊ฐ๋ฅ!
// ํ์ง๋ง ์บก์ํ๋ฅผ ๊นจ๋จ๋ฆฌ๋ ๊ฑฐ๋๊น ์ ๋ง ํ์ํ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํด์ผ ํด.
์ ๋ค๋ฆญ ๋ฉ์๋ ํธ์ถํ๊ธฐ ๐ฏ
public class GenericClass
{
public T CreateInstance<T>() where T : new()
{
return new T();
}
public List<T> CreateList<T>(params T[] items)
{
return new List<T>(items);
}
}
GenericClass obj = new GenericClass();
Type type = obj.GetType();
// ์ ๋ค๋ฆญ ๋ฉ์๋ ์ฐพ๊ธฐ
MethodInfo method = type.GetMethod("CreateList");
// ํ์
์ธ์ ์ง์ (MakeGenericMethod)
MethodInfo genericMethod = method.MakeGenericMethod(typeof(string));
// ํธ์ถ
object result = genericMethod.Invoke(obj, new object[] {
new string[] { "์ฌ๊ณผ", "๋ฐ๋๋", "์ฒด๋ฆฌ" }
});
List<string> fruits = (List<string>)result;
Console.WriteLine($"๊ณผ์ผ ๊ฐ์: {fruits.Count}"); // 3
๐ฆ ํ๋กํผํฐ์ ํ๋ ๊ฐ ์ฝ๊ณ ์ฐ๊ธฐ
๋ฆฌํ๋ ์
์ผ๋ก ๊ฐ์ฒด์ ํ๋กํผํฐ๋ ํ๋ ๊ฐ์ ๋์ ์ผ๋ก ์ฝ๊ณ ์ธ ์ ์์ด! ๐
์ด๊ฑด ํนํ ์ง๋ ฌํ๋ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉํ ๋ ์์ฒญ ์ ์ฉํด.
Person person = new Person("๋ฐ์ํฌ", 32);
Type type = person.GetType();
// ํ๋กํผํฐ ๊ฐ ์ฝ๊ธฐ
PropertyInfo nameProp = type.GetProperty("Name");
object nameValue = nameProp.GetValue(person);
Console.WriteLine($"์ด๋ฆ: {nameValue}"); // "๋ฐ์ํฌ"
PropertyInfo ageProp = type.GetProperty("Age");
object ageValue = ageProp.GetValue(person);
Console.WriteLine($"๋์ด: {ageValue}"); // 32
// ํ๋กํผํฐ ๊ฐ ์ฐ๊ธฐ
nameProp.SetValue(person, "์ต๋ฏผ์");
ageProp.SetValue(person, 40);
Console.WriteLine($"๋ณ๊ฒฝ๋ ์ด๋ฆ: {person.Name}"); // "์ต๋ฏผ์"
Console.WriteLine($"๋ณ๊ฒฝ๋ ๋์ด: {person.Age}"); // 40
// ๋ชจ๋ ํ๋กํผํฐ ์ํํ๋ฉด์ ๊ฐ ์ถ๋ ฅ
Console.WriteLine("\n๐ ๋ชจ๋ ํ๋กํผํฐ ๊ฐ:");
foreach (PropertyInfo prop in type.GetProperties())
{
object value = prop.GetValue(person);
Console.WriteLine($"{prop.Name}: {value}");
}
private ํ๋ ์ ๊ทผํ๊ธฐ ๐ต๏ธ
Type type = typeof(Person);
Person person = new Person("์คํ์ด", 28);
// private ํ๋ ์ฐพ๊ธฐ
FieldInfo secretField = type.GetField("_secret",
BindingFlags.NonPublic | BindingFlags.Instance);
if (secretField != null)
{
// private ํ๋ ๊ฐ ์ฝ๊ธฐ
object secretValue = secretField.GetValue(person);
Console.WriteLine($"๋น๋ฐ ์ ๋ณด: {secretValue}"); // "๋น๋ฐ์ด์ผ!"
// private ํ๋ ๊ฐ ๋ณ๊ฒฝ
secretField.SetValue(person, "์ด์ ๋น๋ฐ์ด ์๋์ผ!");
object newValue = secretField.GetValue(person);
Console.WriteLine($"๋ณ๊ฒฝ๋ ๋น๋ฐ: {newValue}"); // "์ด์ ๋น๋ฐ์ด ์๋์ผ!"
}
์ธ๋ฑ์ ํ๋กํผํฐ ๋ค๋ฃจ๊ธฐ ๐
public class DataCollection
{
private Dictionary<string, object> _data = new Dictionary<string, object>();
public object this[string key]
{
get { return _data.ContainsKey(key) ? _data[key] : null; }
set { _data[key] = value; }
}
}
DataCollection collection = new DataCollection();
Type type = collection.GetType();
// ์ธ๋ฑ์ ํ๋กํผํฐ ์ฐพ๊ธฐ (์ด๋ฆ์ "Item")
PropertyInfo indexer = type.GetProperty("Item");
// ์ธ๋ฑ์๋ก ๊ฐ ์ค์
indexer.SetValue(collection, "์๋
ํ์ธ์!", new object[] { "greeting" });
// ์ธ๋ฑ์๋ก ๊ฐ ์ฝ๊ธฐ
object value = indexer.GetValue(collection, new object[] { "greeting" });
Console.WriteLine(value); // "์๋
ํ์ธ์!"
๐ท๏ธ ์ดํธ๋ฆฌ๋ทฐํธ(Attribute) ํ์ฉํ๊ธฐ
์ดํธ๋ฆฌ๋ทฐํธ๋ ์ฝ๋์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ด์ผ! ๐จ
๋ฆฌํ๋ ์
๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ ๋ง ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๋ง๋ค ์ ์์ด.
์๋ฅผ ๋ค์ด, ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์ API ์๋ํฌ์ธํธ๋ฅผ ์๋์ผ๋ก ์์ฑํ๊ฑฐ๋,
์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์๋ํํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ง! ๐ช
์ปค์คํ ์ดํธ๋ฆฌ๋ทฐํธ ๋ง๋ค๊ธฐ
// ์ ํจ์ฑ ๊ฒ์ฌ์ฉ ์ดํธ๋ฆฌ๋ทฐํธ
[AttributeUsage(AttributeTargets.Property)]
public class RequiredAttribute : Attribute
{
public string ErrorMessage { get; set; }
public RequiredAttribute(string errorMessage = "ํ์ ํญ๋ชฉ์
๋๋ค.")
{
ErrorMessage = errorMessage;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class RangeAttribute : Attribute
{
public int Min { get; set; }
public int Max { get; set; }
public string ErrorMessage { get; set; }
public RangeAttribute(int min, int max)
{
Min = min;
Max = max;
ErrorMessage = $"๊ฐ์ {min}์์ {max} ์ฌ์ด์ฌ์ผ ํฉ๋๋ค.";
}
}
// ์ดํธ๋ฆฌ๋ทฐํธ ์ฌ์ฉ
public class UserRegistration
{
[Required("์ฌ์ฉ์ ์ด๋ฆ์ ํ์์
๋๋ค!")]
public string Username { get; set; }
[Required]
public string Email { get; set; }
[Range(18, 100)]
public int Age { get; set; }
public string PhoneNumber { get; set; } // ์ ํ ์ฌํญ
}
๋ฆฌํ๋ ์ ์ผ๋ก ์ดํธ๋ฆฌ๋ทฐํธ ์ฝ๊ณ ์ ํจ์ฑ ๊ฒ์ฌํ๊ธฐ โ
public class Validator
{
public static List<string> Validate(object obj)
{
List<string> errors = new List<string>();
Type type = obj.GetType();
foreach (PropertyInfo prop in type.GetProperties())
{
// Required ์ดํธ๋ฆฌ๋ทฐํธ ํ์ธ
var requiredAttr = prop.GetCustomAttribute<RequiredAttribute>();
if (requiredAttr != null)
{
object value = prop.GetValue(obj);
if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
{
errors.Add($"{prop.Name}: {requiredAttr.ErrorMessage}");
}
}
// Range ์ดํธ๋ฆฌ๋ทฐํธ ํ์ธ
var rangeAttr = prop.GetCustomAttribute<RangeAttribute>();
if (rangeAttr != null)
{
object value = prop.GetValue(obj);
if (value is int intValue)
{
if (intValue < rangeAttr.Min || intValue > rangeAttr.Max)
{
errors.Add($"{prop.Name}: {rangeAttr.ErrorMessage}");
}
}
}
}
return errors;
}
}
// ์ฌ์ฉ ์์
UserRegistration user = new UserRegistration
{
Username = "", // ๋น์ด์์ - ์๋ฌ!
Email = "test@example.com",
Age = 15 // ๋ฒ์ ๋ฐ - ์๋ฌ!
};
List<string> errors = Validator.Validate(user);
if (errors.Count > 0)
{
Console.WriteLine("โ ์ ํจ์ฑ ๊ฒ์ฌ ์คํจ:");
foreach (string error in errors)
{
Console.WriteLine($" โข {error}");
}
}
else
{
Console.WriteLine("โ
์ ํจ์ฑ ๊ฒ์ฌ ํต๊ณผ!");
}
// ์ถ๋ ฅ:
// โ ์ ํจ์ฑ ๊ฒ์ฌ ์คํจ:
// โข Username: ์ฌ์ฉ์ ์ด๋ฆ์ ํ์์
๋๋ค!
// โข Age: ๊ฐ์ 18์์ 100 ์ฌ์ด์ฌ์ผ ํฉ๋๋ค.
์ฌ๋ฌ ์ดํธ๋ฆฌ๋ทฐํธ ํ ๋ฒ์ ๊ฐ์ ธ์ค๊ธฐ ๐ฏ
[Serializable]
[Obsolete("์ด ํด๋์ค๋ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ต๋๋ค. NewPerson์ ์ฌ์ฉํ์ธ์.")]
public class OldPerson
{
public string Name { get; set; }
}
Type type = typeof(OldPerson);
// ๋ชจ๋ ์ดํธ๋ฆฌ๋ทฐํธ ๊ฐ์ ธ์ค๊ธฐ
object[] attributes = type.GetCustomAttributes(false);
Console.WriteLine($"์ดํธ๋ฆฌ๋ทฐํธ ๊ฐ์: {attributes.Length}");
foreach (var attr in attributes)
{
Console.WriteLine($" โข {attr.GetType().Name}");
if (attr is ObsoleteAttribute obsolete)
{
Console.WriteLine($" ๋ฉ์์ง: {obsolete.Message}");
}
}
// ํน์ ์ดํธ๋ฆฌ๋ทฐํธ๋ง ํ์ธ
bool isSerializable = type.IsDefined(typeof(SerializableAttribute), false);
Console.WriteLine($"์ง๋ ฌํ ๊ฐ๋ฅ? {isSerializable}"); // True
๐ง Assembly ๋ค๋ฃจ๊ธฐ - DLL ๋์ ๋ก๋ฉ
Assembly๋ .NET์ ๋ฐฐํฌ ๋จ์์ผ. DLL์ด๋ EXE ํ์ผ์ด์ง! ๐ฆ
๋ฆฌํ๋ ์
์ ์ฌ์ฉํ๋ฉด ๋ฐํ์์ ์ด์
๋ธ๋ฆฌ๋ฅผ ๋ก๋ํ๊ณ ๊ทธ ์์ ํ์
์ ์ฌ์ฉํ ์ ์์ด.
ํ๋ฌ๊ทธ์ธ ์์คํ
์ ๋ง๋ค ๋ ํ์์ ์ธ ๊ธฐ์ ์ด์ผ! ๐
// ํ์ฌ ์คํ ์ค์ธ ์ด์
๋ธ๋ฆฌ ๊ฐ์ ธ์ค๊ธฐ
Assembly currentAssembly = Assembly.GetExecutingAssembly();
Console.WriteLine($"ํ์ฌ ์ด์
๋ธ๋ฆฌ: {currentAssembly.FullName}");
// ํน์ ํ์
์ด ์ํ ์ด์
๋ธ๋ฆฌ ๊ฐ์ ธ์ค๊ธฐ
Assembly stringAssembly = typeof(string).Assembly;
Console.WriteLine($"String์ด ์ํ ์ด์
๋ธ๋ฆฌ: {stringAssembly.GetName().Name}");
// ์ด์
๋ธ๋ฆฌ์์ ๋ชจ๋ ํ์
๊ฐ์ ธ์ค๊ธฐ
Type[] types = currentAssembly.GetTypes();
Console.WriteLine($"\n๐ ์ด์
๋ธ๋ฆฌ ๋ด ํ์
๊ฐ์: {types.Length}");
foreach (Type type in types.Take(10)) // ์ฒ์ 10๊ฐ๋ง
{
Console.WriteLine($" โข {type.FullName}");
}
// ํน์ ์กฐ๊ฑด์ ํ์
๋ง ํํฐ๋ง
var publicClasses = types.Where(t => t.IsClass && t.IsPublic);
Console.WriteLine($"\n๊ณต๊ฐ ํด๋์ค ๊ฐ์: {publicClasses.Count()}");
// ํน์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํ์
์ฐพ๊ธฐ
public interface IPlugin
{
string Name { get; }
void Execute();
}
var pluginTypes = types.Where(t =>
typeof(IPlugin).IsAssignableFrom(t) &&
!t.IsInterface &&
!t.IsAbstract);
Console.WriteLine($"\n๐ ํ๋ฌ๊ทธ์ธ ํ์
๊ฐ์: {pluginTypes.Count()}");
foreach (var pluginType in pluginTypes)
{
Console.WriteLine($" โข {pluginType.Name}");
}
์ธ๋ถ DLL ๋์ ์ผ๋ก ๋ก๋ํ๊ธฐ ๐
// ๋ฐฉ๋ฒ 1: ํ์ผ ๊ฒฝ๋ก๋ก ๋ก๋
Assembly assembly = Assembly.LoadFrom(@"C:\Plugins\MyPlugin.dll");
// ๋ฐฉ๋ฒ 2: ์ด์
๋ธ๋ฆฌ ์ด๋ฆ์ผ๋ก ๋ก๋ (GAC๋ ์ฑ ๋๋ ํ ๋ฆฌ์์ ๊ฒ์)
Assembly assembly2 = Assembly.Load("MyPlugin, Version=1.0.0.0, Culture=neutral");
// ๋ฐฉ๋ฒ 3: ๋ฐ์ดํธ ๋ฐฐ์ด๋ก ๋ก๋ (๋ฉ๋ชจ๋ฆฌ์์)
byte[] assemblyBytes = File.ReadAllBytes(@"C:\Plugins\MyPlugin.dll");
Assembly assembly3 = Assembly.Load(assemblyBytes);
// ๋ก๋๋ ์ด์
๋ธ๋ฆฌ์์ ํ์
์ฐพ๊ธฐ
Type pluginType = assembly.GetType("MyPlugin.MainPlugin");
if (pluginType != null)
{
// ํ๋ฌ๊ทธ์ธ ์ธ์คํด์ค ์์ฑ
object plugin = Activator.CreateInstance(pluginType);
// IPlugin ์ธํฐํ์ด์ค๋ก ์บ์คํ
if (plugin is IPlugin iPlugin)
{
Console.WriteLine($"ํ๋ฌ๊ทธ์ธ ์ด๋ฆ: {iPlugin.Name}");
iPlugin.Execute();
}
}
// ์ด์
๋ธ๋ฆฌ์ ๋ชจ๋ ๋ฆฌ์์ค ๋์ด
string[] resourceNames = assembly.GetManifestResourceNames();
Console.WriteLine("\n๐ ์๋ฒ ๋๋ ๋ฆฌ์์ค:");
foreach (string name in resourceNames)
{
Console.WriteLine($" โข {name}");
}
ํ๋ฌ๊ทธ์ธ ์์คํ ๊ตฌํ ์์ ๐ฎ
public class PluginManager
{
private List<IPlugin> _plugins = new List<IPlugin>();
public void LoadPlugins(string pluginDirectory)
{
if (!Directory.Exists(pluginDirectory))
{
Console.WriteLine($"ํ๋ฌ๊ทธ์ธ ๋๋ ํ ๋ฆฌ๊ฐ ์์ต๋๋ค: {pluginDirectory}");
return;
}
// ๋๋ ํ ๋ฆฌ์ ๋ชจ๋ DLL ํ์ผ ๊ฒ์
string[] dllFiles = Directory.GetFiles(pluginDirectory, "*.dll");
foreach (string dllFile in dllFiles)
{
try
{
// DLL ๋ก๋
Assembly assembly = Assembly.LoadFrom(dllFile);
// IPlugin์ ๊ตฌํํ ํ์
์ฐพ๊ธฐ
var pluginTypes = assembly.GetTypes()
.Where(t => typeof(IPlugin).IsAssignableFrom(t) &&
!t.IsInterface &&
!t.IsAbstract);
foreach (Type pluginType in pluginTypes)
{
// ํ๋ฌ๊ทธ์ธ ์ธ์คํด์ค ์์ฑ
IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
_plugins.Add(plugin);
Console.WriteLine($"โ
ํ๋ฌ๊ทธ์ธ ๋ก๋ ์ฑ๊ณต: {plugin.Name}");
}
}
catch (Exception ex)
{
Console.WriteLine($"โ {Path.GetFileName(dllFile)} ๋ก๋ ์คํจ: {ex.Message}");
}
}
Console.WriteLine($"\n์ด {_plugins.Count}๊ฐ์ ํ๋ฌ๊ทธ์ธ์ด ๋ก๋๋์์ต๋๋ค.");
}
public void ExecuteAllPlugins()
{
Console.WriteLine("\n๐ ๋ชจ๋ ํ๋ฌ๊ทธ์ธ ์คํ:");
foreach (var plugin in _plugins)
{
Console.WriteLine($"\n--- {plugin.Name} ---");
plugin.Execute();
}
}
public IPlugin GetPlugin(string name)
{
return _plugins.FirstOrDefault(p =>
p.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
}
}
// ์ฌ์ฉ ์์
PluginManager manager = new PluginManager();
manager.LoadPlugins(@"C:\MyApp\Plugins");
manager.ExecuteAllPlugins();
// ํน์ ํ๋ฌ๊ทธ์ธ๋ง ์คํ
IPlugin specificPlugin = manager.GetPlugin("DataProcessor");
specificPlugin?.Execute();
โก ์ฑ๋ฅ ์ต์ ํ - ๋ฆฌํ๋ ์ ์ ๋๋ ค!
์์งํ ๋งํ๋ฉด, ๋ฆฌํ๋ ์
์ ๋๋ ค. ๐
์ผ๋ฐ์ ์ธ ๋ฉ์๋ ํธ์ถ๋ณด๋ค 10๋ฐฐ์์ 100๋ฐฐ๊น์ง ๋๋ฆด ์ ์์ด.
ํ์ง๋ง ๊ฑฑ์ ๋ง! ์ต์ ํ ๋ฐฉ๋ฒ์ด ์๊ฑฐ๋ . ๐ช
โข ํ์ ์ ๋ณด๋ฅผ ๋ฐํ์์ ๊ฒ์ํด์ผ ํจ
โข ๋ฉ์๋ ํธ์ถ ์ ๋งค๊ฐ๋ณ์ ํ์ ๊ฒ์ฆ
โข Boxing/Unboxing ์ค๋ฒํค๋
โข JIT ์ปดํ์ผ๋ฌ ์ต์ ํ ๋ถ๊ฐ
โข ๋ณด์ ๊ฒ์ฌ ์ํ
์ต์ ํ ๋ฐฉ๋ฒ 1: ์บ์ฑ ํ์ฉ ๐พ
public class ReflectionCache
{
private static Dictionary<string, MethodInfo> _methodCache
= new Dictionary<string, MethodInfo>();
private static Dictionary<string, PropertyInfo> _propertyCache
= new Dictionary<string, PropertyInfo>();
public static MethodInfo GetMethod(Type type, string methodName)
{
string key = $"{type.FullName}.{methodName}";
if (!_methodCache.ContainsKey(key))
{
MethodInfo method = type.GetMethod(methodName);
_methodCache[key] = method;
}
return _methodCache[key];
}
public static PropertyInfo GetProperty(Type type, string propertyName)
{
string key = $"{type.FullName}.{propertyName}";
if (!_propertyCache.ContainsKey(key))
{
PropertyInfo property = type.GetProperty(propertyName);
_propertyCache[key] = property;
}
return _propertyCache[key];
}
}
// ์ฌ์ฉ ์์
Type type = typeof(Person);
// ์ฒซ ๋ฒ์งธ ํธ์ถ: ๋ฆฌํ๋ ์
์ผ๋ก ๊ฒ์ (๋๋ฆผ)
MethodInfo method1 = ReflectionCache.GetMethod(type, "SayHello");
// ๋ ๋ฒ์งธ ํธ์ถ: ์บ์์์ ๊ฐ์ ธ์ด (๋น ๋ฆ!)
MethodInfo method2 = ReflectionCache.GetMethod(type, "SayHello");
์ต์ ํ ๋ฐฉ๋ฒ 2: Delegate ์ฌ์ฉ ๐
// ๋ฆฌํ๋ ์
์ผ๋ก ๋ฉ์๋๋ฅผ ์ฐพ์ ํ Delegate๋ก ๋ณํ
public class FastInvoker
{
private static Dictionary<string, Delegate> _delegateCache
= new Dictionary<string, Delegate>();
public static Func<T, TResult> CreateGetter<T, TResult>(string propertyName)
{
string key = $"{typeof(T).FullName}.{propertyName}";
if (!_delegateCache.ContainsKey(key))
{
PropertyInfo property = typeof(T).GetProperty(propertyName);
MethodInfo getMethod = property.GetGetMethod();
// Delegate ์์ฑ
Func<T, TResult> getter =
(Func<T, TResult>)Delegate.CreateDelegate(
typeof(Func<T, TResult>), getMethod);
_delegateCache[key] = getter;
}
return (Func<T, TResult>)_delegateCache[key];
}
public static Action<T, TValue> CreateSetter<T, TValue>(string propertyName)
{
string key = $"{typeof(T).FullName}.{propertyName}.Set";
if (!_delegateCache.ContainsKey(key))
{
PropertyInfo property = typeof(T).GetProperty(propertyName);
MethodInfo setMethod = property.GetSetMethod();
Action<T, TValue> setter =
(Action<T, TValue>)Delegate.CreateDelegate(
typeof(Action<T, TValue>), setMethod);
_delegateCache[key] = setter;
}
return (Action<T, TValue>)_delegateCache[key];
}
}
// ์ฌ์ฉ ์์
Person person = new Person("ํ
์คํธ", 25);
// Getter ์์ฑ (ํ ๋ฒ๋ง)
var nameGetter = FastInvoker.CreateGetter<Person, string>("Name");
// ์ดํ ํธ์ถ์ ์ผ๋ฐ ๋ฉ์๋ ํธ์ถ๋งํผ ๋น ๋ฆ!
string name = nameGetter(person); // ๋งค์ฐ ๋น ๋ฆ!
// Setter ์์ฑ
var nameSetter = FastInvoker.CreateSetter<Person, string>("Name");
nameSetter(person, "์ ์ด๋ฆ"); // ๋งค์ฐ ๋น ๋ฆ!
์ต์ ํ ๋ฐฉ๋ฒ 3: Expression Tree ์ฌ์ฉ ๐ณ
using System.Linq.Expressions;
public class ExpressionHelper
{
public static Func<T> CreateConstructor<T>() where T : new()
{
// Expression Tree๋ก ์์ฑ์ ํธ์ถ ์ฝ๋ ์์ฑ
NewExpression newExp = Expression.New(typeof(T));
LambdaExpression lambda = Expression.Lambda<Func<T>>(newExp);
// ์ปดํ์ผํด์ Delegate๋ก ๋ณํ
return (Func<T>)lambda.Compile();
}
public static Func<object> CreateConstructor(Type type)
{
NewExpression newExp = Expression.New(type);
LambdaExpression lambda = Expression.Lambda<Func<object>>(
Expression.Convert(newExp, typeof(object)));
return (Func<object>)lambda.Compile();
}
public static Func<T, TProperty> CreatePropertyGetter<T, TProperty>(
string propertyName)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "obj");
MemberExpression property = Expression.Property(parameter, propertyName);
LambdaExpression lambda = Expression.Lambda<Func<T, TProperty>>(
property, parameter);
return (Func<T, TProperty>)lambda.Compile();
}
}
// ์ฌ์ฉ ์์
// ์์ฑ์ Delegate ์์ฑ
var personFactory = ExpressionHelper.CreateConstructor<Person>();
// ์ด์ ๊ฐ์ฒด ์์ฑ์ด new Person()๊ณผ ๊ฑฐ์ ๊ฐ์ ์๋!
Person p1 = personFactory();
Person p2 = personFactory();
Person p3 = personFactory();
// ํ๋กํผํฐ Getter ์์ฑ
var ageGetter = ExpressionHelper.CreatePropertyGetter<Person, int>("Age");
int age = ageGetter(p1); // ๋งค์ฐ ๋น ๋ฆ!
์ฑ๋ฅ ๋น๊ต ๋ฒค์น๋งํฌ ๐
using System.Diagnostics;
public class PerformanceTest
{
public static void ComparePerformance()
{
Person person = new Person("ํ
์คํธ", 30);
int iterations = 1000000;
Stopwatch sw = new Stopwatch();
// 1. ์ผ๋ฐ ํธ์ถ
sw.Start();
for (int i = 0; i < iterations; i++)
{
string name = person.Name;
}
sw.Stop();
Console.WriteLine($"์ผ๋ฐ ํธ์ถ: {sw.ElapsedMilliseconds}ms");
// 2. ๋ฆฌํ๋ ์
(์บ์ฑ ์์)
PropertyInfo prop = typeof(Person).GetProperty("Name");
sw.Restart();
for (int i = 0; i < iterations; i++)
{
object name = prop.GetValue(person);
}
sw.Stop();
Console.WriteLine($"๋ฆฌํ๋ ์
(์บ์ฑ ์์): {sw.ElapsedMilliseconds}ms");
// 3. ๋ฆฌํ๋ ์
(์บ์ฑ ์์)
PropertyInfo cachedProp = ReflectionCache.GetProperty(typeof(Person), "Name");
sw.Restart();
for (int i = 0; i < iterations; i++)
{
object name = cachedProp.GetValue(person);
}
sw.Stop();
Console.WriteLine($"๋ฆฌํ๋ ์
(์บ์ฑ): {sw.ElapsedMilliseconds}ms");
// 4. Delegate ์ฌ์ฉ
var getter = FastInvoker.CreateGetter<Person, string>("Name");
sw.Restart();
for (int i = 0; i < iterations; i++)
{
string name = getter(person);
}
sw.Stop();
Console.WriteLine($"Delegate: {sw.ElapsedMilliseconds}ms");
// 5. Expression Tree
var exprGetter = ExpressionHelper.CreatePropertyGetter<Person, string>("Name");
sw.Restart();
for (int i = 0; i < iterations; i++)
{
string name = exprGetter(person);
}
sw.Stop();
Console.WriteLine($"Expression Tree: {sw.ElapsedMilliseconds}ms");
}
}
// ์คํ ๊ฒฐ๊ณผ ์์:
// ์ผ๋ฐ ํธ์ถ: 5ms
// ๋ฆฌํ๋ ์
(์บ์ฑ ์์): 850ms
// ๋ฆฌํ๋ ์
(์บ์ฑ): 720ms
// Delegate: 12ms
// Expression Tree: 8ms
โข ๋ฆฌํ๋ ์ ๊ฒฐ๊ณผ๋ ํญ์ ์บ์ฑํ๊ธฐ
โข ๋ฐ๋ณต ํธ์ถ์ด ๋ง๋ค๋ฉด Delegate๋ Expression Tree ์ฌ์ฉ
โข ์ด๊ธฐํ ์์๋ง ๋ฆฌํ๋ ์ ์ฌ์ฉํ๊ณ , ๋ฐํ์์๋ ์บ์๋ ์ ๋ณด ํ์ฉ
โข ์ฑ๋ฅ์ด ์ค์ํ์ง ์์ ๋ถ๋ถ(์ค์ ๋ก๋ ๋ฑ)์๋ง ์ง์ ๋ฆฌํ๋ ์ ์ฌ์ฉ
โข ํ๋กํ์ผ๋ง์ผ๋ก ๋ณ๋ชฉ ์ง์ ํ์ ํ ์ต์ ํ
๐จ ์ค์ ํ์ฉ ์์ - JSON ์ง๋ ฌํ ๊ตฌํ
์ด์ ๋ฐฐ์ด ๊ฑธ ์ข
ํฉํด์ ๊ฐ๋จํ JSON ์ง๋ ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง๋ค์ด๋ณผ๊น? ๐ ๏ธ
์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์ API ์๋ต์ ๋ง๋ค ๋ ์ ์ฉํ๊ฒ ์ธ ์ ์์ด!
using System.Text;
public class SimpleJsonSerializer
{
public static string Serialize(object obj)
{
if (obj == null)
return "null";
Type type = obj.GetType();
// ๊ธฐ๋ณธ ํ์
์ฒ๋ฆฌ
if (type.IsPrimitive || type == typeof(string))
{
return SerializePrimitive(obj);
}
// ๋ฐฐ์ด/๋ฆฌ์คํธ ์ฒ๋ฆฌ
if (obj is IEnumerable enumerable && type != typeof(string))
{
return SerializeEnumerable(enumerable);
}
// ๊ฐ์ฒด ์ฒ๋ฆฌ
return SerializeObject(obj);
}
private static string SerializePrimitive(object obj)
{
if (obj is string str)
return $"\"{str}\"";
if (obj is bool b)
return b.ToString().ToLower();
return obj.ToString();
}
private static string SerializeEnumerable(IEnumerable enumerable)
{
StringBuilder sb = new StringBuilder();
sb.Append("[");
bool first = true;
foreach (object item in enumerable)
{
if (!first)
sb.Append(",");
sb.Append(Serialize(item));
first = false;
}
sb.Append("]");
return sb.ToString();
}
private static string SerializeObject(object obj)
{
Type type = obj.GetType();
PropertyInfo[] properties = type.GetProperties(
BindingFlags.Public | BindingFlags.Instance);
StringBuilder sb = new StringBuilder();
sb.Append("{");
bool first = true;
foreach (PropertyInfo prop in properties)
{
// ์ฝ๊ธฐ ๊ฐ๋ฅํ ํ๋กํผํฐ๋ง
if (!prop.CanRead)
continue;
if (!first)
sb.Append(",");
string propName = prop.Name;
object propValue = prop.GetValue(obj);
sb.Append($"\"{propName}\":");
sb.Append(Serialize(propValue));
first = false;
}
sb.Append("}");
return sb.ToString();
}
}
// ์ฌ์ฉ ์์
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public bool InStock { get; set; }
public List<string> Tags { get; set; }
}
Product product = new Product
{
Id = 1,
Name = "C# ํ๋ก๊ทธ๋๋ฐ ๊ฐ์",
Price = 50000,
InStock = true,
Tags = new List<string> { "ํ๋ก๊ทธ๋๋ฐ", "C#", "์ด๊ธ" }
};
string json = SimpleJsonSerializer.Serialize(product);
Console.WriteLine(json);
// ์ถ๋ ฅ:
// {"Id":1,"Name":"C# ํ๋ก๊ทธ๋๋ฐ ๊ฐ์","Price":50000,"InStock":true,"Tags":["ํ๋ก๊ทธ๋๋ฐ","C#","์ด๊ธ"]}
์ดํธ๋ฆฌ๋ทฐํธ๋ก ์ง๋ ฌํ ์ ์ดํ๊ธฐ ๐๏ธ
[AttributeUsage(AttributeTargets.Property)]
public class JsonIgnoreAttribute : Attribute { }
[AttributeUsage(AttributeTargets.Property)]
public class JsonPropertyAttribute : Attribute
{
public string Name { get; set; }
public JsonPropertyAttribute(string name)
{
Name = name;
}
}
public class User
{
public int Id { get; set; }
[JsonProperty("username")]
public string Name { get; set; }
public string Email { get; set; }
[JsonIgnore]
public string Password { get; set; } // ์ง๋ ฌํ์์ ์ ์ธ
[JsonProperty("is_active")]
public bool IsActive { get; set; }
}
// SimpleJsonSerializer ๊ฐ์
private static string SerializeObject(object obj)
{
Type type = obj.GetType();
PropertyInfo[] properties = type.GetProperties(
BindingFlags.Public | BindingFlags.Instance);
StringBuilder sb = new StringBuilder();
sb.Append("{");
bool first = true;
foreach (PropertyInfo prop in properties)
{
if (!prop.CanRead)
continue;
// JsonIgnore ์ดํธ๋ฆฌ๋ทฐํธ ํ์ธ
if (prop.GetCustomAttribute<JsonIgnoreAttribute>() != null)
continue;
if (!first)
sb.Append(",");
// JsonProperty ์ดํธ๋ฆฌ๋ทฐํธ๋ก ์ด๋ฆ ๋ณ๊ฒฝ
string propName = prop.Name;
var jsonPropAttr = prop.GetCustomAttribute<JsonPropertyAttribute>();
if (jsonPropAttr != null)
{
propName = jsonPropAttr.Name;
}
object propValue = prop.GetValue(obj);
sb.Append($"\"{propName}\":");
sb.Append(Serialize(propValue));
first = false;
}
sb.Append("}");
return sb.ToString();
}
// ์ฌ์ฉ
User user = new User
{
Id = 100,
Name = "ํ๊ธธ๋",
Email = "hong@example.com",
Password = "secret123", // ์ง๋ ฌํ๋์ง ์์
IsActive = true
};
string json = SimpleJsonSerializer.Serialize(user);
Console.WriteLine(json);
// ์ถ๋ ฅ:
// {"Id":100,"username":"ํ๊ธธ๋","Email":"hong@example.com","is_active":true}
๐ ๋ณด์ ๊ณ ๋ ค์ฌํญ
๋ฆฌํ๋ ์
์ ๊ฐ๋ ฅํ์ง๋ง, ๊ทธ๋งํผ ์ํํ ์๋ ์์ด! ๐จ
private ๋ฉค๋ฒ์ ์ ๊ทผํ ์ ์๋ค๋ ๊ฑด ์บก์ํ๋ฅผ ๊นจ๋จ๋ฆด ์ ์๋ค๋ ๋ป์ด๊ฑฐ๋ .
1. ์ ๋ขฐํ ์ ์๋ ์ ๋ ฅ ๊ฒ์ฆ
์ฌ์ฉ์ ์ ๋ ฅ์ผ๋ก ํ์ ์ด๋ฆ์ด๋ ๋ฉ์๋ ์ด๋ฆ์ ๋ฐ์ ๋๋ ๋ฐ๋์ ํ์ดํธ๋ฆฌ์คํธ ๊ฒ์ฆ!
2. ๊ถํ ํ์ธ
private ๋ฉค๋ฒ ์ ๊ทผ ์ ์ ๋ง ํ์ํ์ง ์ฌ๊ณ ํ๊ธฐ
3. ์์ธ ์ฒ๋ฆฌ
๋ฆฌํ๋ ์ ์ ๋ฐํ์ ์๋ฌ๊ฐ ๋ง์ผ๋ ์ฒ ์ ํ ์์ธ ์ฒ๋ฆฌ ํ์
4. ์ฑ๋ฅ ์ํฅ
ํซ ํจ์ค(์์ฃผ ์คํ๋๋ ์ฝ๋)์์๋ ๋ฆฌํ๋ ์ ์ฌ์ฉ ์์
5. ํ์ ์์ ์ฑ
์ปดํ์ผ ํ์ ํ์ ์ฒดํฌ๋ฅผ ์ฐํํ๋ฏ๋ก ๋ฐํ์ ์๋ฌ ๊ฐ๋ฅ์ฑ ์ฆ๊ฐ
// โ ๋์ ์: ์ฌ์ฉ์ ์
๋ ฅ์ ๊ทธ๋๋ก ์ฌ์ฉ
public object InvokeMethod(string typeName, string methodName, object[] args)
{
Type type = Type.GetType(typeName); // ์ํ!
MethodInfo method = type.GetMethod(methodName); // ์ํ!
return method.Invoke(null, args);
}
// โ
์ข์ ์: ํ์ดํธ๋ฆฌ์คํธ ๊ฒ์ฆ
public object InvokeMethod(string typeName, string methodName, object[] args)
{
// ํ์ฉ๋ ํ์
๋ชฉ๋ก
var allowedTypes = new HashSet<string>
{
"MyApp.Calculator",
"MyApp.StringHelper",
"MyApp.DateHelper"
};
if (!allowedTypes.Contains(typeName))
{
throw new SecurityException($"ํ์
'{typeName}'์ ํ์ฉ๋์ง ์์ต๋๋ค.");
}
Type type = Type.GetType(typeName);
if (type == null)
{
throw new ArgumentException($"ํ์
'{typeName}'์ ์ฐพ์ ์ ์์ต๋๋ค.");
}
// ํ์ฉ๋ ๋ฉ์๋ ๋ชฉ๋ก
var allowedMethods = new HashSet<string> { "Add", "Subtract", "Format" };
if (!allowedMethods.Contains(methodName))
{
throw new SecurityException($"๋ฉ์๋ '{methodName}'์ ํ์ฉ๋์ง ์์ต๋๋ค.");
}
MethodInfo method = type.GetMethod(methodName);
if (method == null)
{
throw new ArgumentException($"๋ฉ์๋ '{methodName}'์ ์ฐพ์ ์ ์์ต๋๋ค.");
}
try
{
return method.Invoke(null, args);
}
catch (TargetInvocationException ex)
{
// ์ค์ ์์ธ๋ฅผ ๋ค์ ๋์ง๊ธฐ
throw ex.InnerException ?? ex;
}
}
// ์์ ํ ํ๋กํผํฐ ์ค์
public void SetPropertySafely<T>(T obj, string propertyName, object value)
{
Type type = typeof(T);
PropertyInfo property = type.GetProperty(propertyName);
if (property == null)
{
throw new ArgumentException($"ํ๋กํผํฐ '{propertyName}'์ด ์กด์ฌํ์ง ์์ต๋๋ค.");
}
if (!property.CanWrite)
{
throw new InvalidOperationException($"ํ๋กํผํฐ '{propertyName}'์ ์ฝ๊ธฐ ์ ์ฉ์
๋๋ค.");
}
// ํ์
ํธํ์ฑ ๊ฒ์ฌ
if (value != null && !property.PropertyType.IsAssignableFrom(value.GetType()))
{
throw new ArgumentException(
$"๊ฐ์ ํ์
({value.GetType().Name})์ด ํ๋กํผํฐ ํ์
({property.PropertyType.Name})๊ณผ ํธํ๋์ง ์์ต๋๋ค.");
}
try
{
property.SetValue(obj, value);
}
catch (Exception ex)
{
throw new InvalidOperationException(
$"ํ๋กํผํฐ '{propertyName}' ์ค์ ์ค ์ค๋ฅ ๋ฐ์", ex);
}
}
๐ ๊ณ ๊ธ ๊ธฐ๋ฒ - ๋์ ํ์ ์์ฑ
๋ฆฌํ๋ ์
์ ๋ํ์! ๋ฐํ์์ ์์ ํ ์๋ก์ด ํ์
์ ๋ง๋ค ์ ์์ด! ๐ญ
System.Reflection.Emit ๋ค์์คํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด
IL(Intermediate Language) ์ฝ๋๋ฅผ ์ง์ ์์ฑํด์ ์๋ก์ด ํด๋์ค๋ฅผ ๋ง๋ค ์ ์์ง.
using System.Reflection.Emit;
public class DynamicTypeBuilder
{
public static Type CreateDynamicType(string typeName,
Dictionary<string, Type> properties)
{
// ๋์ ์ด์
๋ธ๋ฆฌ ์์ฑ
AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.Run);
// ๋์ ๋ชจ๋ ์์ฑ
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");
// ๋์ ํ์
์์ฑ
TypeBuilder typeBuilder = moduleBuilder.DefineType(
typeName,
TypeAttributes.Public | TypeAttributes.Class);
// ๊ฐ ํ๋กํผํฐ ์ถ๊ฐ
foreach (var prop in properties)
{
AddProperty(typeBuilder, prop.Key, prop.Value);
}
// ํ์
์์ฑ
return typeBuilder.CreateType();
}
private static void AddProperty(TypeBuilder typeBuilder,
string propertyName, Type propertyType)
{
// private ํ๋ ์์ฑ
FieldBuilder fieldBuilder = typeBuilder.DefineField(
"_" + propertyName.ToLower(),
propertyType,
FieldAttributes.Private);
// public ํ๋กํผํฐ ์์ฑ
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(
propertyName,
PropertyAttributes.HasDefault,
propertyType,
null);
// Getter ๋ฉ์๋ ์์ฑ
MethodBuilder getterBuilder = typeBuilder.DefineMethod(
"get_" + propertyName,
MethodAttributes.Public | MethodAttributes.SpecialName |
MethodAttributes.HideBySig,
propertyType,
Type.EmptyTypes);
ILGenerator getterIL = getterBuilder.GetILGenerator();
getterIL.Emit(OpCodes.Ldarg_0);
getterIL.Emit(OpCodes.Ldfld, fieldBuilder);
getterIL.Emit(OpCodes.Ret);
// Setter ๋ฉ์๋ ์์ฑ
MethodBuilder setterBuilder = typeBuilder.DefineMethod(
"set_" + propertyName,
MethodAttributes.Public | MethodAttributes.SpecialName |
MethodAttributes.HideBySig,
null,
new Type[] { propertyType });
ILGenerator setterIL = setterBuilder.GetILGenerator();
setterIL.Emit(OpCodes.Ldarg_0);
setterIL.Emit(OpCodes.Ldarg_1);
setterIL.Emit(OpCodes.Stfld, fieldBuilder);
setterIL.Emit(OpCodes.Ret);
// ํ๋กํผํฐ์ getter/setter ์ฐ๊ฒฐ
propertyBuilder.SetGetMethod(getterBuilder);
propertyBuilder.SetSetMethod(setterBuilder);
}
}
// ์ฌ์ฉ ์์
var properties = new Dictionary<string, Type>
{
{ "Id", typeof(int) },
{ "Name", typeof(string) },
{ "CreatedDate", typeof(DateTime) },
{ "IsActive", typeof(bool) }
};
Type dynamicType = DynamicTypeBuilder.CreateDynamicType("DynamicEntity", properties);
// ๋์ ํ์
์ ์ธ์คํด์ค ์์ฑ
object instance = Activator.CreateInstance(dynamicType);
// ํ๋กํผํฐ ์ค์
PropertyInfo idProp = dynamicType.GetProperty("Id");
idProp.SetValue(instance, 123);
PropertyInfo nameProp = dynamicType.GetProperty("Name");
nameProp.SetValue(instance, "๋์ ๊ฐ์ฒด");
PropertyInfo dateProp = dynamicType.GetProperty("CreatedDate");
dateProp.SetValue(instance, DateTime.Now);
// ํ๋กํผํฐ ์ฝ๊ธฐ
Console.WriteLine($"Id: {idProp.GetValue(instance)}");
Console.WriteLine($"Name: {nameProp.GetValue(instance)}");
Console.WriteLine($"CreatedDate: {dateProp.GetValue(instance)}");
์ด ๊ธฐ๋ฒ์ ORM ํ๋ ์์ํฌ๋ ํ๋ก์ ๊ฐ์ฒด ์์ฑ์ ์ฌ์ฉ๋ผ.
Entity Framework ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ด๋ถ์ ์ผ๋ก ์ด๋ฐ ๋ฐฉ์์ ์ฌ์ฉํ์ง! ๐ฅ
๐ ์ค๋ฌด ํ์ฉ ์๋๋ฆฌ์ค
์, ์ด์ ์ค์ ๋ก ์ด๋ป๊ฒ ํ์ฉํ๋์ง ๋ช ๊ฐ์ง ์๋๋ฆฌ์ค๋ฅผ ๋ณผ๊น? ๐ผ
์๋๋ฆฌ์ค 1: ์ค์ ํ์ผ ์๋ ๋ฐ์ธ๋ฉ โ๏ธ
public class ConfigurationBinder
{
public static T Bind<T>(Dictionary<string, string> config) where T : new()
{
T instance = new T();
Type type = typeof(T);
foreach (var kvp in config)
{
PropertyInfo property = type.GetProperty(kvp.Key,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (property != null && property.CanWrite)
{
try
{
// ๋ฌธ์์ด์ ํ๋กํผํฐ ํ์
์ผ๋ก ๋ณํ
object value = Convert.ChangeType(kvp.Value, property.PropertyType);
property.SetValue(instance, value);
}
catch (Exception ex)
{
Console.WriteLine($"'{kvp.Key}' ๋ฐ์ธ๋ฉ ์คํจ: {ex.Message}");
}
}
}
return instance;
}
}
public class AppSettings
{
public string DatabaseConnection { get; set; }
public int MaxConnections { get; set; }
public bool EnableLogging { get; set; }
public double Timeout { get; set; }
}
// ์ฌ์ฉ
var configData = new Dictionary<string, string>
{
{ "DatabaseConnection", "Server=localhost;Database=MyDB" },
{ "MaxConnections", "100" },
{ "EnableLogging", "true" },
{ "Timeout", "30.5" }
};
AppSettings settings = ConfigurationBinder.Bind<AppSettings>(configData);
Console.WriteLine($"DB ์ฐ๊ฒฐ: {settings.DatabaseConnection}");
Console.WriteLine($"์ต๋ ์ฐ๊ฒฐ: {settings.MaxConnections}");
Console.WriteLine($"๋ก๊น
ํ์ฑํ: {settings.EnableLogging}");
Console.WriteLine($"ํ์์์: {settings.Timeout}์ด");
์๋๋ฆฌ์ค 2: ๊ฐ๋จํ ์์กด์ฑ ์ฃผ์ ์ปจํ ์ด๋ ๐
public class SimpleContainer
{
private Dictionary<Type, Type> _registrations = new Dictionary<Type, Type>();
private Dictionary<Type, object> _singletons = new Dictionary<Type, object>();
public void Register<TInterface, TImplementation>()
where TImplementation : TInterface
{
_registrations[typeof(TInterface)] = typeof(TImplementation);
}
public void RegisterSingleton<TInterface, TImplementation>()
where TImplementation : TInterface
{
Type interfaceType = typeof(TInterface);
Type implementationType = typeof(TImplementation);
_registrations[interfaceType] = implementationType;
// ์ฑ๊ธํค ์ธ์คํด์ค ์์ฑ
object instance = CreateInstance(implementationType);
_singletons[interfaceType] = instance;
}
public T Resolve<T>()
{
return (T)Resolve(typeof(T));
}
private object Resolve(Type type)
{
// ์ฑ๊ธํค ํ์ธ
if (_singletons.ContainsKey(type))
{
return _singletons[type];
}
// ๋ฑ๋ก๋ ํ์
ํ์ธ
if (_registrations.ContainsKey(type))
{
Type implementationType = _registrations[type];
return CreateInstance(implementationType);
}
// ๊ตฌ์ฒด ํ์
์ด๋ฉด ์ง์ ์์ฑ
if (!type.IsAbstract && !type.IsInterface)
{
return CreateInstance(type);
}
throw new InvalidOperationException($"ํ์
'{type.Name}'์ ํด๊ฒฐํ ์ ์์ต๋๋ค.");
}
private object CreateInstance(Type type)
{
// ์์ฑ์ ์ฐพ๊ธฐ (๋งค๊ฐ๋ณ์๊ฐ ๊ฐ์ฅ ๋ง์ ๊ฒ)
ConstructorInfo[] constructors = type.GetConstructors();
ConstructorInfo constructor = constructors
.OrderByDescending(c => c.GetParameters().Length)
.First();
// ์์ฑ์ ๋งค๊ฐ๋ณ์ ํด๊ฒฐ
ParameterInfo[] parameters = constructor.GetParameters();
object[] parameterInstances = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
parameterInstances[i] = Resolve(parameters[i].ParameterType);
}
// ์ธ์คํด์ค ์์ฑ
return constructor.Invoke(parameterInstances);
}
}
// ์ฌ์ฉ ์์
public interface ILogger
{
void Log(string message);
}
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"[LOG] {message}");
}
}
public interface IDataService
{
void SaveData(string data);
}
public class DataService : IDataService
{
private readonly ILogger _logger;
public DataService(ILogger logger)
{
_logger = logger;
}
public void SaveData(string data)
{
_logger.Log($"๋ฐ์ดํฐ ์ ์ฅ ์ค: {data}");
// ์ค์ ์ ์ฅ ๋ก์ง...
}
}
// ์ปจํ
์ด๋ ์ค์
SimpleContainer container = new SimpleContainer();
container.RegisterSingleton<ILogger, ConsoleLogger>();
container.Register<IDataService, DataService>();
// ์์กด์ฑ ์๋ ์ฃผ์
!
IDataService dataService = container.Resolve<IDataService>();
dataService.SaveData("์ค์ํ ์ ๋ณด"); // [LOG] ๋ฐ์ดํฐ ์ ์ฅ ์ค: ์ค์ํ ์ ๋ณด
์๋๋ฆฌ์ค 3: ๊ฐ์ฒด ๋ณต์ฌ(Deep Clone) ๐
public class ObjectCloner
{
public static T DeepClone<T>(T source)
{
if (source == null)
return default(T);
Type type = typeof(T);
// ๊ฐ ํ์
์ด๋ string์ ๊ทธ๋๋ก ๋ฐํ
if (type.IsValueType || type == typeof(string))
return source;
// ์ ์ธ์คํด์ค ์์ฑ
T clone = Activator.CreateInstance<T>();
// ๋ชจ๋ ํ๋ ๋ณต์ฌ (private ํฌํจ)
FieldInfo[] fields = type.GetFields(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
object fieldValue = field.GetValue(source);
if (fieldValue != null)
{
// ์ฐธ์กฐ ํ์
์ด๋ฉด ์ฌ๊ท์ ์ผ๋ก ๋ณต์ฌ
if (field.FieldType.IsClass && field.FieldType != typeof(string))
{
MethodInfo cloneMethod = typeof(ObjectCloner)
.GetMethod("DeepClone")
.MakeGenericMethod(field.FieldType);
fieldValue = cloneMethod.Invoke(null, new[] { fieldValue });
}
field.SetValue(clone, fieldValue);
}
}
return clone;
}
}
// ์ฌ์ฉ ์์
public class Address
{
public string City { get; set; }
public string Street { get; set; }
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Address Address { get; set; }
}
Person original = new Person
{
Name = "๊น์ฒ ์",
Age = 30,
Address = new Address { City = "์์ธ", Street = "๊ฐ๋จ๋๋ก" }
};
Person cloned = ObjectCloner.DeepClone(original);
// ๋ณต์ฌ๋ณธ ์์
cloned.Name = "์ด์ํฌ";
cloned.Address.City = "๋ถ์ฐ";
Console.WriteLine($"์๋ณธ: {original.Name}, {original.Address.City}");
// ์ถ๋ ฅ: ์๋ณธ: ๊น์ฒ ์, ์์ธ
Console.WriteLine($"๋ณต์ฌ๋ณธ: {cloned.Name}, {cloned.Address.City}");
// ์ถ๋ ฅ: ๋ณต์ฌ๋ณธ: ์ด์ํฌ, ๋ถ์ฐ
๐ ์ฌ๋ฅ๋ท์์ ๋ฆฌํ๋ ์ ํ์ฉํ๊ธฐ
์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์ ๊ฐ๋ฐํ๋ค๋ฉด ๋ฆฌํ๋ ์
์ ์ด๋ป๊ฒ ํ์ฉํ ์ ์์๊น? ๐ค
๋ช ๊ฐ์ง ์ค์ฉ์ ์ธ ์์ ๋ฅผ ์ดํด๋ณด์!
์ฌ๋ฅ ์นดํ ๊ณ ๋ฆฌ ์๋ ๋ฑ๋ก ์์คํ ๐
// ์ฌ๋ฅ ์นดํ
๊ณ ๋ฆฌ๋ฅผ ๋ํ๋ด๋ ์ดํธ๋ฆฌ๋ทฐํธ
[AttributeUsage(AttributeTargets.Class)]
public class TalentCategoryAttribute : Attribute
{
public string CategoryName { get; set; }
public string Description { get; set; }
public int DisplayOrder { get; set; }
public TalentCategoryAttribute(string categoryName)
{
CategoryName = categoryName;
}
}
// ์ฌ๋ฅ ์๋น์ค ์ธํฐํ์ด์ค
public interface ITalentService
{
string GetServiceName();
decimal GetPrice();
void Execute();
}
// ๊ตฌ์ฒด์ ์ธ ์ฌ๋ฅ ์๋น์ค๋ค
[TalentCategory("ํ๋ก๊ทธ๋๋ฐ", Description = "์ํํธ์จ์ด ๊ฐ๋ฐ ๊ด๋ จ", DisplayOrder = 1)]
public class CSharpTutorService : ITalentService
{
public string GetServiceName() => "C# ํ๋ก๊ทธ๋๋ฐ ๊ณผ์ธ";
public decimal GetPrice() => 50000;
public void Execute() => Console.WriteLine("C# ๊ฐ์๋ฅผ ์์ํฉ๋๋ค!");
}
[TalentCategory("๋์์ธ", Description = "๊ทธ๋ํฝ ๋์์ธ", DisplayOrder = 2)]
public class LogoDesignService : ITalentService
{
public string GetServiceName() => "๋ก๊ณ ๋์์ธ";
public decimal GetPrice() => 100000;
public void Execute() => Console.WriteLine("๋ก๊ณ ๋์์ธ์ ์์ํฉ๋๋ค!");
}
[TalentCategory("๋ฒ์ญ", Description = "์ธ์ด ๋ฒ์ญ ์๋น์ค", DisplayOrder = 3)]
public class TranslationService : ITalentService
{
public string GetServiceName() => "์ํ ๋ฒ์ญ";
public decimal GetPrice() => 30000;
public void Execute() => Console.WriteLine("๋ฒ์ญ์ ์์ํฉ๋๋ค!");
}
// ์ฌ๋ฅ ๋ ์ง์คํธ๋ฆฌ - ์๋์ผ๋ก ๋ชจ๋ ์ฌ๋ฅ ์๋น์ค ๊ฒ์
public class TalentRegistry
{
private List<Type> _talentServices = new List<Type>();
public void ScanAssembly()
{
Assembly assembly = Assembly.GetExecutingAssembly();
// ITalentService๋ฅผ ๊ตฌํํ ๋ชจ๋ ํ์
์ฐพ๊ธฐ
var serviceTypes = assembly.GetTypes()
.Where(t => typeof(ITalentService).IsAssignableFrom(t) &&
!t.IsInterface &&
!t.IsAbstract);
_talentServices.AddRange(serviceTypes);
Console.WriteLine($"๐ {_talentServices.Count}๊ฐ์ ์ฌ๋ฅ ์๋น์ค๋ฅผ ์ฐพ์์ต๋๋ค!\n");
}
public void DisplayAllTalents()
{
// ์นดํ
๊ณ ๋ฆฌ๋ณ๋ก ๊ทธ๋ฃนํ
var groupedByCategory = _talentServices
.Select(t => new
{
Type = t,
Attribute = t.GetCustomAttribute<TalentCategoryAttribute>()
})
.Where(x => x.Attribute != null)
.GroupBy(x => x.Attribute.CategoryName)
.OrderBy(g => g.First().Attribute.DisplayOrder);
foreach (var category in groupedByCategory)
{
Console.WriteLine($"๐ ์นดํ
๊ณ ๋ฆฌ: {category.Key}");
Console.WriteLine($" ์ค๋ช
: {category.First().Attribute.Description}\n");
foreach (var item in category)
{
ITalentService service = (ITalentService)Activator.CreateInstance(item.Type);
Console.WriteLine($" โจ {service.GetServiceName()}");
Console.WriteLine($" ๊ฐ๊ฒฉ: {service.GetPrice():N0}์");
Console.WriteLine($" ํ์
: {item.Type.Name}\n");
}
}
}
public ITalentService CreateService(string serviceName)
{
Type serviceType = _talentServices
.FirstOrDefault(t =>
{
ITalentService temp = (ITalentService)Activator.CreateInstance(t);
return temp.GetServiceName().Equals(serviceName,
StringComparison.OrdinalIgnoreCase);
});
if (serviceType != null)
{
return (ITalentService)Activator.CreateInstance(serviceType);
}
return null;
}
}
// ์ฌ์ฉ ์์
TalentRegistry registry = new TalentRegistry();
registry.ScanAssembly();
registry.DisplayAllTalents();
// ํน์ ์๋น์ค ์คํ
ITalentService service = registry.CreateService("C# ํ๋ก๊ทธ๋๋ฐ ๊ณผ์ธ");
if (service != null)
{
Console.WriteLine($"\n๐ฏ '{service.GetServiceName()}' ์๋น์ค๋ฅผ ์์ํฉ๋๋ค!");
service.Execute();
}
์ด๋ ๊ฒ ํ๋ฉด ์๋ก์ด ์ฌ๋ฅ ์๋น์ค๋ฅผ ์ถ๊ฐํ ๋๋ง๋ค
์ดํธ๋ฆฌ๋ทฐํธ๋ง ๋ถ์ด๋ฉด ์๋์ผ๋ก ์์คํ
์ ๋ฑ๋ก๋ผ! ๐
์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์ ์๋ฐฑ ๊ฐ์ ์๋น์ค๋ฅผ ๊ด๋ฆฌํ ๋ ์ ๋ง ์ ์ฉํ์ง!
๐ก ๋ฒ ์คํธ ํ๋ํฐ์ค์ ํ
1. ์บ์ฑ์ ํ์
Type, MethodInfo, PropertyInfo ๋ฑ์ ํ ๋ฒ ๊ฐ์ ธ์ค๋ฉด ์บ์ฑํ๊ธฐ
2. BindingFlags ๋ช ์์ ์ผ๋ก ์ง์
๊ธฐ๋ณธ๊ฐ์ ์์กดํ์ง ๋ง๊ณ ํ์ํ ํ๋๊ทธ๋ฅผ ๋ช ํํ ์ง์
3. ์์ธ ์ฒ๋ฆฌ ์ฒ ์ ํ
TargetInvocationException์ InnerException ํ์ธ
4. ์ฑ๋ฅ ์ธก์
๋ฆฌํ๋ ์ ์ฌ์ฉ ์ ํ ์ฑ๋ฅ ๋น๊ต ํ์
5. ๋์ ๊ณ ๋ ค
์ ๋ค๋ฆญ, ์ธํฐํ์ด์ค, Delegate ๋ฑ์ผ๋ก ํด๊ฒฐ ๊ฐ๋ฅํ์ง ๋จผ์ ๊ฒํ
6. ๋ฌธ์ํ
์ ๋ฆฌํ๋ ์ ์ ์ฌ์ฉํ๋์ง ์ฃผ์์ผ๋ก ๋ช ํํ ์ค๋ช
7. ๋จ์ ํ ์คํธ
๋ฆฌํ๋ ์ ์ฝ๋๋ ์ปดํ์ผ ํ์ ์ฒดํฌ๊ฐ ์ ๋๋ฏ๋ก ํ ์คํธ ํ์
8. ๋ฒ์ ๊ด๋ฆฌ
์ด์ ๋ธ๋ฆฌ ๋ฒ์ ์ด ๋ฐ๋๋ฉด ํ์ ์ด๋ฆ๋ ๋ฐ๋ ์ ์์ผ๋ ์ฃผ์
์ฌ์ฉํ๊ธฐ ์ข์ ๊ฒฝ์ฐ:
โข ํ๋ฌ๊ทธ์ธ ์์คํ ๊ตฌํ
โข ํ๋ ์์ํฌ/๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ฐ๋ฐ
โข ์ง๋ ฌํ/์ญ์ง๋ ฌํ
โข ์์กด์ฑ ์ฃผ์ ์ปจํ ์ด๋
โข ์ฝ๋ ์์ฑ ๋๊ตฌ
โข ํ ์คํธ ํ๋ ์์ํฌ
ํผํด์ผ ํ๋ ๊ฒฝ์ฐ:
โข ์ผ๋ฐ์ ์ธ ๋น์ฆ๋์ค ๋ก์ง
โข ์ฑ๋ฅ์ด ์ค์ํ ํซ ํจ์ค
โข ์ปดํ์ผ ํ์์ ํ์ ์ ์ ์ ์๋ ๊ฒฝ์ฐ
โข ๊ฐ๋จํ ๊ฐ์ฒด ์์ฑ์ด๋ ๋ฉ์๋ ํธ์ถ
๐ฌ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์, ์ฌ๊ธฐ๊น์ง C# ๋ฆฌํ๋ ์
๊ณผ ๋์ ํ๋ก๊ทธ๋๋ฐ์ ๋ํด ์์๋ดค์ด! ๐
์ฒ์์ ์ด๋ ต๊ฒ ๋๊ปด์ง ์ ์์ง๋ง, ํ ๋ฒ ์ต์ํด์ง๋ฉด ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ๊ฐ ๋ผ.
๋ฆฌํ๋ ์
์ ๋ง์น ํ๋ก๊ทธ๋จ์ X-ray ๊ฐ์.
์ฝ๋์ ๋ด๋ถ ๊ตฌ์กฐ๋ฅผ ๋ค์ฌ๋ค๋ณด๊ณ , ๋ฐํ์์ ๋์ ์ผ๋ก ์กฐ์ํ ์ ์์ง.
ํ์ง๋ง ๊ฐ๋ ฅํ ๋งํผ ์ ์คํ๊ฒ ์ฌ์ฉํด์ผ ํด! โก
์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์ ๊ฐ๋ฐํ๊ฑฐ๋, ํ๋ ์์ํฌ๋ฅผ ๋ง๋ค๊ฑฐ๋,
์ ์ฐํ ์์คํ
์ ๊ตฌ์ถํ ๋ ๋ฆฌํ๋ ์
์ ์ ๋ง ์ ์ฉํ ์น๊ตฌ๊ฐ ๋ ๊ฑฐ์ผ.
์ฑ๋ฅ๊ณผ ์ ์ฐ์ฑ ์ฌ์ด์ ๊ท ํ์ ์ ๋ง์ถ๋ฉด์ ํ์ฉํด๋ณด์! ๐ช
์ด ๊ธ์ด ๋์์ด ๋์๋ค๋ฉด, ์ฌ๋ฅ๋ท์์ ๋ค๋ฅธ ์ ์ฉํ ์ง์๋ค๋ ์ฐพ์๋ณด๊ณ ,
๋์ ์ฌ๋ฅ๋ ๊ณต์ ํด๋ณด๋ ๊ฑด ์ด๋? ๐
์ฐ๋ฆฌ ๋ชจ๋ ํจ๊ป ์ฑ์ฅํ๋ ๊ฐ๋ฐ์๊ฐ ๋์! ๐
๋ฆฌํ๋ ์ ์ผ๋ก ๋ ์ ์ฐํ๊ณ ๊ฐ๋ ฅํ ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๋ณด์ธ์!
์ง๋ฌธ์ด๋ ํผ๋๋ฐฑ์ ์ธ์ ๋ ํ์์ ๋๋ค! ๐ฌ
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.