質問

私のコード:

System.Resources.ResourceManager resourceManager = GetResourceManager();
string str = resourceManager.GetString("delete", new CultureInfo(1033));

.NET 2.0の下にコンパイルされた現在のプロジェクトでは、すべてが例外として機能します。変数 str LCID 1033のリソース文字列が含まれています - 消去, 、 これで結構です。

現在、ターゲットフレームワーク.NET 4.0の下でプロジェクトを再コンパイルした.NET 4.0にアップグレードしています。 .NET 4.0アセンブリとしてコンパイルされるようになり、例外をスローします System.ArgumentNullexception メッセージ付き 値はヌルにすることはできません。。スタックトレース:

   at System.Threading.Monitor.Enter(Object obj)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture, Boolean createIfNotExists, Boolean tryParents, StackCrawlMark& stackMark)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
   at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)

ここで興味深いのはStacktraceです。 resourcemanager.internalgetResourceset それは呼び出します Monitor.enter nullオブジェクト付き。しかし、私は方法を呼び出します GetString ヌルパラメーターではありません GetString( "Delete"、New CultureInfo(1033)).

このバグは似ているようです system.threading.monitor.enterのsystem.argumentnullexception. 。たぶん、モニターのバグ。

更新:オブジェクトでデバッガーを見るとき resourceManager.ResourceSets.Items[2].Value.Table["delete"] 次に、文字列値「削除」が含まれます。プロパティアイテム[2]ここでは、LCID 1033を指しています。これは、リソースマネージャーにリソースキー用のローカライズされた文字列が既に含まれていることを意味します 消去 言語で 1033. 。エラーがどこにあるか知っている人はいますか?

役に立ちましたか?

解決

また、リソースセットは.NET 4.0の下で時代遅れとしてマークされているため、ストレージに独自の辞書を宣言して使用する必要があると思います。

他のヒント

私は自分自身に答えるのを見つけました。詳細は次のとおりです。このようなResourceManagerのカスタム実装があります。

public class DatabaseResourceManager : System.Resources.ResourceManager 
{
  public DatabaseResourceManager(int applicationID, string bundle) 
  {
    foreach (int languageID in ResourceProvider.Provider.GetLanguages(applicationID))
    {
      DatabaseResourceReader r = new DatabaseResourceReader(applicationID, bundle, languageID);
      ResourceSets.Add(new CultureInfo(languageID), new ResourceSet(r));
    }
}

.NET 2.0ではうまく機能しますが、.NET 4.0では、ResourceManagerの実装で何かが変更されました。 this._resourcesets (後に使用されます internalgetResourceset Monitor.enter用)。しかし、.NET 4.0では、パラメーターレスコンストラクターはプライベートフィールドをインスタンス化しません this._resourcesets したがって、後で失敗します(説明したように)。

これを解決するために、カスタムリソースマネージャーを書き直す必要があります。

public class DatabaseResourceManager : System.Resources.ResourceManager 
{
  public DatabaseResourceManager(int applicationID, string bundle) 
  {
    ResourceSets = new Hashtable();
    this.applicationID = applicationID;
    this.bundle = bundle;
  }

  protected override ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
  {
    if (this.ResourceSets.Contains(culture.Name))
        return this.ResourceSets[culture.Name] as ResourceSet;

    lock (syncLock)
    {
        if (this.ResourceSets.Contains(culture.Name))
            return this.ResourceSets[culture.Name] as ResourceSet;

        DatabaseResourceReader r = new DatabaseResourceReader(applicationID, bundle, culture.LCID);
        ResourceSet rs = new ResourceSet(r);

        this.ResourceSets.Add(culture.Name, rs);

        return rs;
    }
  }
}

ここに「魔法」は、私が方法を上書きしなければならないということです internalgetResourceset カスタムストレージ(DB)からリソースをロードし、指定されたカルチャーの「リソースセット」を返します。今では魅力のように機能します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top