using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace DDD
{
///
/// 바인딩 컨텍스트 - ViewModel과 View 간의 데이터 바인딩을 관리
///
public class BindingContext
{
private readonly Dictionary> _bindings = new();
private readonly Dictionary _converters = new();
private INotifyPropertyChanged _dataContext;
///
/// 데이터 컨텍스트 (ViewModel) 설정
///
/// 바인딩할 ViewModel
public void SetDataContext(INotifyPropertyChanged dataContext)
{
if (_dataContext != null)
_dataContext.PropertyChanged -= OnPropertyChanged;
_dataContext = dataContext;
if (_dataContext != null)
{
_dataContext.PropertyChanged += OnPropertyChanged;
RefreshAllBindings();
}
}
///
/// 속성 바인딩 추가
///
/// 바인딩할 속성 경로
/// 바인딩 타겟
/// 값 변환기 (선택사항)
public void Bind(string propertyPath, IBindingTarget target, IValueConverter converter = null)
{
if (!_bindings.ContainsKey(propertyPath))
_bindings[propertyPath] = new List();
_bindings[propertyPath].Add(target);
if (converter != null)
_converters[propertyPath] = converter;
// 즉시 초기값 설정
UpdateBinding(propertyPath);
}
///
/// 속성 변경 이벤트 핸들러
///
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
UpdateBinding(e.PropertyName);
}
///
/// 특정 속성의 바인딩 업데이트
///
/// 업데이트할 속성 경로
private void UpdateBinding(string propertyPath)
{
if (!_bindings.ContainsKey(propertyPath)) return;
var value = GetPropertyValue(propertyPath);
// 컨버터 적용
if (_converters.TryGetValue(propertyPath, out var converter))
value = converter.Convert(value);
foreach (var target in _bindings[propertyPath])
{
target.UpdateValue(value);
}
}
///
/// 속성 값 가져오기 (리플렉션 사용)
///
/// 속성 경로
/// 속성 값
private object GetPropertyValue(string propertyPath)
{
if (_dataContext == null) return null;
// 중첩 속성 지원 (예: "ItemData.Name")
var properties = propertyPath.Split('.');
object current = _dataContext;
foreach (var prop in properties)
{
if (current == null) return null;
var property = current.GetType().GetProperty(prop);
current = property?.GetValue(current);
}
return current;
}
///
/// 모든 바인딩 새로고침
///
private void RefreshAllBindings()
{
foreach (var propertyPath in _bindings.Keys)
{
UpdateBinding(propertyPath);
}
}
///
/// 리소스 정리
///
public void Dispose()
{
if (_dataContext != null)
_dataContext.PropertyChanged -= OnPropertyChanged;
_bindings.Clear();
_converters.Clear();
}
}
///
/// 속성 경로 캐시 - 성능 최적화를 위한 리플렉션 결과 캐싱
///
public static class PropertyPathCache
{
private static readonly Dictionary> _cache = new();
///
/// 캐시된 PropertyInfo 가져오기
///
/// 타입
/// 속성 이름
/// PropertyInfo
public static PropertyInfo GetProperty(Type type, string propertyName)
{
if (!_cache.ContainsKey(type))
_cache[type] = new Dictionary();
if (!_cache[type].ContainsKey(propertyName))
_cache[type][propertyName] = type.GetProperty(propertyName);
return _cache[type][propertyName];
}
}
}