.NET · C# Extension Kütüphanesi

Nesnenize dokunmadan,
ona geçici bilgi bağlayın.

TemporaryPropertiesExtensions, mevcut sınıflarınızı hiç değiştirmeden herhangi bir reference type nesneye çalışma zamanında anahtar–değer verisi ekleyip yönetmenizi sağlayan, ConditionalWeakTable tabanlı, thread‑safe ve GC dostu bir extension kütüphanesidir.

MIT Lisans 0 harici bağımlılık Thread-Safe GC-Safe
object graphruntime
class Customer
Id1
Name"Ahmet Yılmaz"
ConditionalWeakTable overlay
IsProcessedtrue
Score95
Problem

Bazen bir bilgi, modelin parçası değildir.

Sadece işlem süresince ihtiyaç duyduğunuz bir alanı domain modeline eklemek, o modeli kalıcı olarak kirletir — üstelik database'e, serialization'a ve iş kurallarına hiç ait olmadan.

// Gerçek modele eklemek istemediğiniz alan:
public class Customer
{
  public int Id { get; set; }
  public string Name { get; set; }
  // public bool IsProcessed { get; set; } ❌
}

// Bunun yerine:
customer.AddTemporary(
  x => x.Name,
  "Geçici İsim"
);
×

Domain modelinin bir parçası değil — sadece o anki işlem için var.

×

Database'e ait değil — bir ORM kolonuna dönüşmemeli.

×

Serialization'da görünmemeli — API contract'ını kirletmemeli.

×

Sadece mevcut işlem süresince gerekli — kalıcı bir state değil.

×

Belki üçüncü parti bir sınıf — kaynak koduna erişiminiz bile yok.

Nasıl Çalışır

Geçici değer, gerçek property'nin üzerine overlay gibi biner.

Aşağıdaki nesne üzerinde deneyin: Name alanına geçici bir değer ekleyin, GetWithTemporary'nin sonucunun nasıl değiştiğini — gerçek property'nin ise hiç dokunulmadığını — görün.

Interactive · ConditionalWeakTable Overlay

customer.GetWithTemporary(x => x.Name)

Gerçek nesne değişmez; temporary store nesnenin yaşam döngüsüne ConditionalWeakTable ile bağlanır, üzerine hiçbir fiziksel property eklenmez.

Customer instance
Id1
Name"Ahmet Yılmaz"
Temporary["Name"]
Çağrı Sonucu
GetWithTemporary(x => x.Name)
"Ahmet Yılmaz"
Gerçek Property
customer.Name
"Ahmet Yılmaz" (değişmedi)

Henüz temporary değer eklenmedi — GetWithTemporary, gerçek property'yi (compiled getter cache üzerinden) okuyor.

Öne Çıkan Özellikler

Küçük bir API yüzeyi, ciddi bir mühendislik altyapısı.

🧩

Dinamik Temporary Property

Nesneye fiziksel property eklemeden geçici değer saklar.

🧠

Expression API

x => x.Property şeklinde strongly-typed, IntelliSense destekli kullanım.

🔤

Name-Based API

Property/field adına string ile, dinamik senaryolar için erişim.

Compiled Getter Cache

Reflection maliyetini tekrar tekrar ödememek için getter'lar compile edilip cache'lenir.

♻️

Type-Aware Weak Cache

Getter cache'i ConditionalWeakTable<Type,...> ile Type yaşam döngüsüne bağlanır.

🛡️

GC-Safe Storage

Temporary store, nesneyi güçlü referansla tutmaz — GC'nin işini engellemez.

🔒

Thread-Safe

Store ve getter cache için ConcurrentDictionary kullanılır.

🚀

Span-Based Parsing

String dönüşümlerinde allocation azaltmak için ReadOnlySpan<char> kullanılır.

🌍

Culture Fallback

Numeric/date parsing önce Invariant, sonra Current Culture ile denenir.

🔄

Primitive Conversion

IConvertible üzerinden farklı primitive tipler arasında otomatik dönüşüm.

🎯

Enum Parsing

String değerlerden case-insensitive enum dönüşümü.

🧬

Property + Field Desteği

Public ve non-public instance property/field erişimi desteklenir.

Mimari

İki bağımsız, birbirinden ayrık mekanizma.

Kütüphane, temporary değerleri ve compiled getter'ları birbirinden tamamen ayrı iki ConditionalWeakTable yapısında tutar — biri nesne, diğeri Type yaşam döngüsüne bağlıdır.

1. Temporary Object Storage

ConditionalWeakTable<object, ConcurrentDictionary<string,object>>
Object (customer)
Temporary Dictionary
"IsProcessed" → true
"Score" → 95

2. Type-Aware Getter Cache

ConditionalWeakTable<Type, ConcurrentDictionary<string,Func<object,object>>>
Type (Customer)
Compiled Getter Dictionary
"Name" → Func<object,object>
"Id" → Func<object,object>
Kullanım

İki API, aynı altyapı.

Strongly-typed Expression API veya dinamik Name-Based API — ikisi de aynı temporary storage üzerinde çalışır, birbirinin yerine kullanılabilir.

Ekle / Oku / Sil
customer.AddTemporary(
  x => x.Name,
  "Geçici İsim"
);

string name = customer.GetWithTemporary(
  x => x.Name
);

customer.RemoveTemporary(x => x.Name);
Öncelik Davranışı
product.Price = 100;

product.AddTemporary(x => x.Price, 250);

// GetWithTemporary → 250 (overlay)
// product.Price → 100 (değişmedi)
var price = product.GetWithTemporary(x => x.Price);
Ekle / Oku / Sil
customer.AddTemporaryByName(
  "Name", "Geçici İsim"
);

string name = customer
  .GetWithTemporaryByName<string>("Name");

customer.RemoveTemporaryByName("Name");
Otomatik Tip Dönüşümü
product.AddTemporaryByName(
  "RuntimePrice", "250"
);

var price = product
  .GetWithTemporaryByName<decimal>(
    "RuntimePrice"
  ); // 250m
Temporary Store Temizleme
customer.ClearTemporary();
// Temporary Values → temizlenir
// Getter Cache → korunur

var props = customer.GetTemporaryProperties();
// IReadOnlyDictionary<string, object>
Getter Cache Temizleme
customer.ClearGetterCacheFor();

TemporaryPropertiesExtensions
  .ClearGetterCacheFor<Customer>();

TemporaryPropertiesExtensions
  .ClearGetterCacheFor<Customer, string>(
    x => x.Name
  );
Kullanım Senaryoları

Nerelerde kullanılabilir?

Domain modelinin parçası olmayan, ama işlem sırasında ihtiyaç duyulan her runtime bilgisi için uygundur.

01

API Response İşleme

Bir API'den gelen DTO'ya, yalnızca response processing sırasında kullanılacak metadata eklenir — DTO'nun kendisine property eklemeye gerek kalmaz.

response.AddTemporaryByName("ProcessedAt", DateTime.UtcNow);
02

Mapping İşlemleri

Bir nesne başka bir modele eşlenirken, işlemin durumunu geçici olarak nesnenin üzerinde taşıyabilirsiniz.

entity.AddTemporaryByName("MappingStatus", "Completed");
03

ORM Entity'leri

Database modelinin parçası olmayan; ValidationResult, ProcessingState, RuntimeScore gibi geçici bilgiler entity üzerinde tutulabilir.

entity.AddTemporaryByName("ValidationResult", result);
04

Pipeline / Processing State

Bir nesnenin pipeline'ın hangi aşamasından geçtiği, aşamalar arasında nesne üzerinde geçici olarak saklanabilir.

item.AddTemporaryByName("ProcessingStage", "Validation");
05

Runtime Metadata (Framework Geliştirme)

Framework veya utility geliştirirken, kullanıcının sınıflarına dokunmadan Source, Validation, Cache State gibi metadata taşınabilir.

obj.AddTemporaryByName("Source", "ExternalSync");
06

Üçüncü Parti Sınıflar

Kaynak koduna müdahale edemediğiniz, başka bir kütüphaneden gelen sınıflar üzerinde bile runtime state taşıyabilirsiniz.

thirdPartyObject.AddTemporaryByName("RuntimeState", "Processed");
Ne Zaman Kullanılmalı?

Her geçici bilgi için doğru araç budur — ama her bilgi için değil.

✅ Uygun olduğu durumlar

  • Geçici runtime metadata gerektiğinde
  • DTO'lara ek state bağlamak istediğinizde
  • Domain modeline işlem bilgisi eklemek istemediğinizde
  • Üçüncü parti sınıflarla çalışırken
  • Mapping / pipeline işlemlerinde
  • Validation state saklarken
  • Reflection tabanlı framework geliştirirken

❌ Uygun olmadığı durumlar

  • Database'e kaydedilecek bilgiler
  • Domain davranışının parçası olan state
  • API contract'ının parçası olan property'ler
  • Serialization ile dışarı aktarılması gereken bilgiler
  • İş kurallarının temel aldığı kalıcı değerler
Karşılaştırma

Geleneksel yaklaşımlara karşı.

YaklaşımModel Değişir mi?GC DostuThread-SafeDynamicGetter Cache
Property eklemekEvetModele bağlı
Wrapper / DecoratorHayırModele bağlıKısmen
Global DictionaryHayır
Her çağrıda ReflectionHayır
ConditionalWeakTable + ReflectionHayırKısmen
TemporaryPropertiesExtensionsHayır
API Referansı

Tüm public metotlar.

Temporary Value API

AddTemporaryExpression ile temporary değer ekler
GetWithTemporaryExpression ile temporary/gerçek değeri getirir
RemoveTemporaryExpression ile temporary değeri siler
AddTemporaryByNameİsimle temporary değer ekler
GetWithTemporaryByNameİsimle temporary/gerçek değeri getirir
RemoveTemporaryByNameİsimle temporary değeri siler
GetTemporaryPropertiesTemporary dictionary'yi getirir
ClearTemporaryNesnenin tüm temporary değerlerini temizler

Getter Cache API

ClearGetterCacheFor(instance)Nesnenin Type'ına ait getter cache'ini temizler
ClearGetterCacheFor<T>()Generic Type getter cache'ini temizler
ClearGetterCacheFor<T,TProp>()Belirli member getter cache'ini temizler
Kurulum

Projenize ekleyin.

Kütüphane şu an tek bir kaynak dosya (TemporaryPropertiesExtensions.cs) olarak dağıtılıyor; harici hiçbir framework gerektirmez, temel .NET API'leri üzerine kuruludur.

Yöntem 1

Repoyu klonlayıp dosyayı projenize ekleyin

git clone https://github.com/DSOpenServer/DSO.Core.TemporaryProperties

# TemporaryPropertiesExtensions.cs dosyasını
# kendi projenize kopyalayın
Yöntem 2

Namespace'i projenize dahil edin

using DSO.Core.TemporaryProperties;

// customer.AddTemporary(...),
// customer.GetWithTemporary(...) hazır
Başlayın

Modelin parçası olmayan bilgiyi,
modele eklemek zorunda değilsiniz.

TemporaryPropertiesExtensions, gerçek nesne modelinizi hiç değiştirmeden, nesnenin yaşam döngüsü boyunca ihtiyaç duyulan geçici bilgileri yönetmeniz için tasarlandı.

GitHub'da İncele →

"Modelin parçası olmayan bilgiyi modele eklemek zorunda değilsin."