アクセス/要求中に同じオブジェクトを使用する - asp.net
質問
私はすべての要求にCommunityPrincipal(実装IPrincipalインタフェース)オブジェクトを作成HttpModuleをしています。私は何とか私はそれを必要とするたびに私はキャストを行うか、それを再度作成することなく、それを得ることができます洙要求ごとにオブジェクトを格納する。
基本的に私は、FormsAuthenticationModuleの仕組みを模倣します。 それはすべての要求に応じて、IPrincipalインターフェイスを実装するオブジェクトをHttpContext.Userプロパティが割り当てられます。
私は何とかHttpContext.MySpecialUserなどを呼び出すことができるようにしたい(またはMySpecialContext.MySpecialUser - 静的クラスを作成することができます)私のオブジェクト(特定の種類)を返しますどの
。私は拡張メソッドを使用することができますが、私はそれが要求時にアクセスできるようにオブジェクトを格納する方法を知らない。
これはどのように達成することができますか?
私は、特定のタイプ( - だけではなくオブジェクトとしてCommunityPrincipal)としてそれを保存したい注意してください。 それはもちろんだけで処理していない他のすべてのスレッド/リクエストで共有されている現在の要求のために利用可能である必要があります。
今私はHttpModuleをしてHttpContext.Userに私のCommunityPrincipalオブジェクトを割り当て、それは私がIPrincipalインターフェイスで定義されてイマイチCommunityPrincipalオブジェクトのプロパティを使用する必要がキャスト毎回行うために私を必要とします。
解決
Context.Userにカスタムプリンシパルを割り当てることは正しいです。うまくいけば、あなたはのApplication_AuthenticateRequestでそれをやってます。
あなたの質問に来て、あなただけのASPXページからユーザオブジェクトにアクセスできますか?もしそうなら、あなたはあなたのためのキャストを含むカスタムベースページを実装することができます。
public class CommunityBasePage : Page
{
new CommunityPrincipal User
{
get { return base.User as CommunityPrincipal; }
}
}
次に、あなたのページがCommunityBasePage
から継承させると、あなたはthis.User
からすべてのプロパティを取得することができるでしょう。
他のヒント
私はあなたがスレッド自体にデータを結合から離れて滞在をお勧めしたいです。あなたはasp.netは、現在または将来のスレッドを使用する方法を制御することはできません。
のデータは非常に多く、それが定義されなければならないので、要求コンテキストに関連付けられて生きて、コンテキストと一緒に死ぬています。それはちょうどそれを置くための適切な場所で、HttpModuleをしてオブジェクトをインスタンス化することも適切です。
キャストは本当に問題の多くではありませんが、あなたは離れているから取得したい場合、私は非常にこれは拡張メソッドがある状況の正確一種である...このためのHttpContextのための拡張メソッドをお勧めします処理するために設計されています。
ここで私はそれを実装したい方法です。
拡張メソッドを置くために、静的クラスを作成します:
public static class ContextExtensions
{
public static CommunityPrinciple GetCommunityPrinciple(this HttpContext context)
{
if(HttpContext.Current.Items["CommunityPrinciple"] != null)
{
return HttpContext.Current.Items["CommunityPrinciple"] as CommunityPrinciple;
}
}
}
あなたのHttpModuleをでちょうどのようなコンテキスト・アイテムのコレクションに校長を置きます
HttpContext.Current.Items.Add("CommunityPrincipal", MyCommunityPrincipal);
あなたが書いたサードパーティのコード、フレームワークのコード、および他のものは、あなたがそこにstroed通常のIPrincipalを改ざんしたの危険にさらさないように、これは、自然な状態での定期的な文脈のユーザープロパティを保持します。インスタンスは、それが有効なユーザーの要求の間に存在します。そして、それだけで任意の正規のHttpContextのメンバーであるかのように、すべての最高は、この方法は、コードに提供されています....そして何のキャストは必要ありません。
あなたはすでにあなたが本当にあなたの目標をacheiveする必要があるすべてはあなたの目標をacheives staticメソッドであるHttpContext.Userプロパティにオブジェクトを格納するので: -
public static class MySpecialContext
{
public static CommunityPrinciple Community
{
get
{
return (CommunityPrinciple)HttpContext.Current.User;
}
}
}
今、あなたのようにCommunityPrincipleを得ることができます: -
var x = MySpecialContext.Community;
しかし、避けるようになったために多くの労力を思わ: -
var x = (CommunityPrinciple)Context.User;
代替のHttpContextに拡張メソッドであろう: -
public static class HttpContextExtensions
{
public static CommunityPrinciple GetCommunity(this HttpContext o)
{
return (CommunityPrinciple)o.User;
}
}
使用それ: -
var x = Context.GetCommunity();
これはかなりきちんとしたのですが、各ファイルに拡張子クラスが使用してリストで定義された名前空間のニーズにそれを含めることを忘れないでくださいする必要がされます。
編集
あなたは、上記のように呼ばれるコード内で行わでもキャストは(ところで、私はこの結論にあなたを導きどのような状況を理解するために本当に興味があると思います)、まだ受け入れられない理由はいくつかの本当に良い理由を持っている瞬間を前提とします。
さらに別の代替がThreadStaticフィールドです: -
public class MyModule : IHttpModule
{
[ThreadStatic]
private static CommunityPrinciple _threadCommunity;
public static CommunityPrinciple Community
{
get
{
return _threadCommunity;
}
}
// Place here your original module code but instead of (or as well as) assigning
// the Context.User store in _threadCommunity.
// Also at the appropriate point in the request lifecyle null the _threadCommunity
}
[ThreadStatic]飾らフィールドは、スレッドあたりの記憶の1つのインスタンスを有することになります。したがって、複数のスレッドが、変更及び_threadCommunityを読み取るが、各フィールドのそれらの特定のインスタンス上で動作することができます。