1

.NET からサードパーティの SOAP API を使用しようとしています。いつものように、C# プロキシ クラスを生成してそれを呼び出したところ、すべて正常に動作しました。

その後、ベンダーと話をしたところ、テナント (データベース) を切り替えるには、別の XML 名前空間を指定する必要があることがわかりました。問題は、名前空間がプロキシ コードに組み込まれていることです。匿名バージョン:

[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")]
[System.Web.Services.WebServiceBindingAttribute(
    Name="eStrangeAPI", Namespace="urn:wsTenantSpecific")]
public partial class eTimeWSService : System.Web.Services.Protocols.SoapHttpClientProtocol {
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", 
        RequestNamespace="urn:wsTenantSpecific:eStrange",
        ResponseNamespace="urn:wsClientSpecificNamespace:eStrange", ...]
    ...
    public string methodCall(ref Param param) {
        ...
    }

wsTenantSpecificそのため、現在使用中のアカウントに応じて名前空間を変更する必要があります。クラスの属性を取得して、その場で変更できます...

var attr = ((WebServiceBindingAttribute[])
    typeof( eTimeWSService ).GetCustomAttributes(
    typeof( WebServiceBindingAttribute ), false ))[ 0 ];
attr.Namespace = "urn:wsADifferentNameSpace";

...しかし、これがどれほどスレッドセーフであるかが心配です。複数のアカウントを同時に接続し、同じプロセス内の異なるスレッドで ASP.NET 要求を実行することができました。

要点: 属性を変更すると、プロセス全体または現在のスレッドのみが変更されますか?

4

2 に答える 2

2

要点: 属性を変更すると、プロセス全体または現在のスレッドのみが変更されますか?

ない。そして両方。場合によります。

属性オブジェクトは、誰かが要求するまで実際には存在しません。それでも、要求するたびに同じインスタンスが返されるという保証はありません。そのため、属性の値を変更して、別の呼び出し元が属性。ただし、一部のシナリオでは、属性インスタンスがキャッシュされる可能性があり、その場合、同じインスタンスを取得する可能性があるため、問題になる可能性があります。しかし!シリアライザーや同様のツールについて話すとき、メタプログラミングとキャッシュされた戦略が使用されている可能性が高いため、実際には毎回属性を検査しているわけではありません。実際、最初に必要になったときに何らかの動的コードを出力した可能性があります。に、そして今、反省の側面を再訪するつもりはまったくありません。

個人的には、別のアプローチを探しています。属性を変更することは、これを行うための良い方法ではありません。

例として、これはhello/を書きますhello(変更は失われます):

using System;
class FooAttribute : Attribute {
    public FooAttribute(string bar) {
        Bar = bar;
    }
    public string Bar { get; set; }
}
[Foo("hello")]
class Program {
    static void Main() {
        WriteFooBar<Program>();
        var d = (FooAttribute)Attribute.GetCustomAttribute(
            typeof(Program), typeof(FooAttribute));
        d.Bar = "world";
        WriteFooBar<Program>();
    }
    static void WriteFooBar<T>() {
        var bar = ((FooAttribute)Attribute.GetCustomAttribute(
            typeof(T), typeof(FooAttribute))).Bar;
        Console.WriteLine(bar);
    }
}

そして、この同様のコードはhello/を書き込みますworld(変更は保持されます):

using System;
using System.ComponentModel;
class FooAttribute : Attribute {
    public FooAttribute(string bar) {
        Bar = bar;
    }
    public string Bar { get; set; }
}
[Foo("hello")]
class Program {
    static void Main() {
        WriteFooBar<Program>();
        var d = (FooAttribute)TypeDescriptor.GetAttributes(typeof(Program))[
            typeof(FooAttribute)];
        d.Bar = "world";
        WriteFooBar<Program>();
    }
    static void WriteFooBar<T>() {
        var bar = ((FooAttribute)TypeDescriptor.GetAttributes(typeof(Program))[
            typeof(FooAttribute)]).Bar;
        Console.WriteLine(bar);
    }
}

(なぜならTypeDescriptor.GetAttributes、タイプごとに実際の属性インスタンスをキャッシュするのに対し、-as はAttribute.GetCustomAttribute呼び出しごとに新しいインスタンスを作成するからです)

于 2013-07-01T13:39:49.910 に答える