DI 프레임 워크는 종속성 주입을 수행하기 위해 제작되었으며 현지화는 서비스 중 하나 일 수 있습니다. 따라서이 경우 DI 프레임 워크 IMO를 사용하는 이유는 없습니다. 은입니다. 아마도 우리는 제공된 ILocalResources
인터페이스에 대해 논의하기 시작해야 할 것입니다. 컴파일 시간 지원에 호의적인데, 제공된 인터페이스가 도움이 될지 확신 할 수 없습니다. 인터페이스가 아마도 시스템에서 가장 많이 변경 될 유형이기 때문입니다. 그리고 그 인터페이스를 구현하는 타입/타입. 아마도 당신은 다른 디자인으로 가야 할 것입니다.
대부분의 현지화 프레임 워크/제공자/공장 (또는 무엇이든)은 모두 문자열 기반입니다. 이것 때문에, 다음과 같은 설계에 대한 생각이 당신이 인터페이스를 변경하지 않고, 기본 메시지 데이터 저장소에 키와 문화를 추가 할 수 있도록 할
public interface ILocalResources
{
string GetStringResource(string key);
string GetStringResource(string key, CultureInfo culture);
}
. 단점은 당연히 키를 변경해서는 안된다는 것입니다. 왜냐하면 그건 아마도 지옥 일 것이기 때문입니다.
또 다른 방법 추상 기본 유형이 될 수 :
public abstract class LocalResources
{
public string OkMessage { get { return this.GetString("OK"); } }
public string CancelMessage { get { return this.GetString("Cancel"); } }
...
protected abstract string GetStringResource(string key,
CultureInfo culture);
private string GetString(string key)
{
Culture culture = CultureInfo.CurrentCulture;
string resource = GetStringResource(key, culture);
// When the resource is not found, fall back to the neutral culture.
while (resource == null && culture != CultureInfo.InvariantCulture)
{
culture = culture.Parent;
resource = this.GetStringResource(key, culture);
}
if (resource == null) throw new KeyNotFoundException(key);
return resource;
}
}
그리고 이러한 유형의 구현은 다음과 같이 수 : 키가 원하기 때문에,
public sealed class SqlLocalResources : LocalResources
{
protected override string GetStringResource(string key,
CultureInfo culture)
{
using (var db = new LocalResourcesContext())
{
return (
from resource in db.StringResources
where resource.Culture == culture.Name
where resource.Key == key
select resource.Value).FirstOrDefault();
}
}
}
를이 방식은 두 세계의 최선을 다한다 ' 응용 프로그램을 통해 분산되어 새로운 속성을 추가하는 작업은 한 곳에서 수행해야합니다.
container.RegisterSingleton<LocalResources>(new SqlLocalResources());
그리고 LocalResources
유형이 모든 작업을 수행 정확히 하나의 추상 메소드를 가지고 있기 때문에,이 요청 방지하기 위해 캐싱을 추가하는 장식을 쉽게 만들 수 있습니다 : 당신의 favorite DI 라이브러리를 사용하면,이 같은 구현을 등록 할 수 있습니다 다음과 같이 당신은 장식을 적용 할 수 있습니다
public sealed class CachedLocalResources : LocalResources
{
private readonly Dictionary<CultureInfo, Dictionary<string, string>> cache =
new Dictionary<CultureInfo, Dictionary<string, string>>();
private readonly LocalResources decoratee;
public CachedLocalResources(LocalResources decoratee) { this.decoratee = decoratee; }
protected override string GetStringResource(string key, CultureInfo culture) {
lock (this.cache) {
string res;
var cultureCache = this.GetCultureCache(culture);
if (!cultureCache.TryGetValue(key, out res)) {
cultureCache[key] = res= this.decoratee.GetStringResource(key, culture);
}
return res;
}
}
private Dictionary<string, string> GetCultureCache(CultureInfo culture) {
Dictionary<string, string> cultureCache;
if (!this.cache.TryGetValue(culture, out cultureCache)) {
this.cache[culture] = cultureCache = new Dictionary<string, string>();
}
return cultureCache;
}
}
: 데이터베이스에서 동일한 데이터
container.RegisterSingleton<LocalResources>(
new CachedLocalResources(new SqlLocalResources()));
하지 마십시오 이 데코레이터는 문자열 리소스를 무기한 캐시하여 메모리 누수가 발생할 수 있으므로 문자열을 WeakReference
개의 인스턴스로 감싸거나 인스턴스에 만료 시간 제한을두고 싶습니다. 그러나 기존 구현을 변경하지 않고도 캐싱을 적용 할 수 있다는 아이디어가 있습니다.
이 정보가 도움이되기를 바랍니다.
"ILocalResources"인터페이스의 확장 메서드를 구현할 수도 있지만, 단점은 속성 대신 메서드가 있다는 것입니다. 그러나 그렇게 나쁘지는 않을 것입니다. – Steven