3

.NET 4 では、コード アクセス セキュリティ (CAS) は非推奨です。暗黙的にそれを使用するメソッドを呼び出すたびに、古い動作にフォールバックする構成スイッチNotSupportedExceptionで解決できるで失敗します。

.NET 3.5 と .NET 4 の両方で使用される共通のライブラリがあるため、CAS メソッドを使用する必要があるかどうかを判断できる必要があります。

たとえば、.NET 3.5 では、次のように呼び出す必要があります。

Assembly.Load(string, Evidence);

一方、.NET 4では呼び出したい

Assembly.Load(string);

を呼び出すLoad(string, Evidence)と、 がスローされNotSupportedExceptionます。

もちろんこれは機能しますが、より良い方法があるかどうか知りたいです。

try
{
    asm = Assembly.Load(someString, someEvidence);
}
catch(NotSupportedException)
{
    asm = Assembly.Load(someString);
}
4

3 に答える 3

1

これは、機能に対して直接コード化されます。

    public static Assembly LoadAssembly(string assembly, Evidence evidence)
    {
        Assembly asm;
        MethodInfo load = 
            typeof(Assembly).GetMethod("Load", 
                                        new Type[] {typeof(string), typeof(Evidence)});

        if (Attribute.IsDefined(load, typeof(ObsoleteAttribute)))
        {
            asm = Assembly.Load(assembly);
        }
        else
        {
            asm = Assembly.Load(assembly, evidence);
        }
        return asm;
    }

このコードは、次の using ステートメントを想定しています。

using System;
using System.Reflection;
using System.Security.Policy;

これが頻繁に呼び出される場合は、このようなものでリフレクション パフォーマンス ヒットを回避できます。

private static bool? _isEvidenceObsolete = null;
public static Assembly AssemblyLoader(string assembly, Evidence evidence)
{
    Assembly asm;
    if (!_isEvidenceObsolete.HasValue)
    {
        MethodInfo load =
           typeof(Assembly).GetMethod("Load",
                                       new Type[] { typeof(string), typeof(Evidence) });
        _isEvidenceObsolete = Attribute.IsDefined(load, typeof(ObsoleteAttribute));
    }

    if (_isEvidenceObsolete.Value)
    {
        asm = Assembly.Load(assembly);
    }
    else
    {
        asm = Assembly.Load(assembly, evidence);
    }
    return asm;
}

編集:パフォーマンス統計がどうなるかを自分で確認する必要がありました。これが得られたものです。

経過時間 (ミリ秒):

Catch Exception: 45331
Reflection: 58
Static Reflection: 1

ベンチマークに使用したコードは次のとおりです。

public static void BenchmarkLoaders()
{
    Stopwatch timer = new Stopwatch();

    // Benchmark catching Exceptions
    timer.Start();
    for (int i = 0; i < 10000; i++)
    {
        NotSupported notSupported = new NotSupported();
        try
        {
            notSupported.ThrowException("Obsoleted Method Call");
        }
        catch (NotSupportedException nse)
        {
            //Do something
        }
    }
    timer.Stop();
    Console.WriteLine("Catch Exception: {0}", timer.ElapsedMilliseconds);
    timer.Reset();

    // Benchmark Reflection
    timer.Start();
    for (int i = 0; i < 10000; i++)
    {
        NotSupported notSupported = new NotSupported();

        notSupported.ReflectAssembly();
    }
    timer.Stop();
    Console.WriteLine("Reflection: {0}", timer.ElapsedMilliseconds);
    timer.Reset();


    // Benchmark Static Reflection
    timer.Start();
    for (int i = 0; i < 10000; i++)
    {
        NotSupported.ReflectAssemblyStatic();
    }
    timer.Stop();
    Console.WriteLine("Static Reflection: {0}", timer.ElapsedMilliseconds);
    timer.Reset();

}

これがNotSupportedクラスです。

public class NotSupported
{
    public void ThrowException(string message)
    {
        throw new NotSupportedException(message);
    }

    public void ReflectAssembly()
    {
        MethodInfo load = 
            typeof(Assembly).GetMethod("Load", 
                                        new Type[] { typeof(string), typeof(Evidence) });

        if (Attribute.IsDefined(load, typeof(ObsoleteAttribute)))
        {
            // Do something
        }
    }

    private static bool? _isEvidenceObsolete = null;
    public static void ReflectAssemblyStatic()
    {
        Assembly asm;
        if (!_isEvidenceObsolete.HasValue)
        {
            MethodInfo load =
               typeof(Assembly).GetMethod("Load",
                                           new Type[] { typeof(string), typeof(Evidence) });
            _isEvidenceObsolete = Attribute.IsDefined(load, typeof(ObsoleteAttribute));
        }

        if (_isEvidenceObsolete.Value)
        {
            //Do Stuff
        }
    }
}

これらは実際の数値ではないことは承知していますが、例外に対するリフレクションの使用について非常に説得力のある議論を提供します。

于 2010-03-31T15:10:16.473 に答える
0

System.Security.HostSecurityManager.DomainPolicy プロパティのゲッターは、従来の CAS ポリシー スイッチが適用されていない場合、.NET 4.0 ですぐに失敗するパブリックな軽量メソッドです。潜在的な例外のコストが 2 回以上発生するのを避けるために、ヘルパー クラスを設定することを検討することをお勧めします。 :

internal static class CasPolicyHelper
{
    private static bool? _isCasPolicyEnabled;

    internal static bool IsCasPolicyEnabled
    {
        get
        {
            if (_isCasPolicyEnabled == null)
            {
                HostSecurityManager hostSecurityManager = new HostSecurityManager();
                try
                {
                    PolicyLevel level = hostSecurityManager.DomainPolicy;
                    _isCasPolicyEnabled = true;
                }
                catch (NotSupportedException)
                {
                    _isCasPolicyEnabled = false;
                }
            }

            return _isCasPolicyEnabled.Value;
        }
    }
}
于 2010-03-29T13:49:20.713 に答える