Jasica.Net

C#, .Net, SQL i nie tylko

Sprawdzanie atrybytów

Istnieje kilka sposobów sprawdzania obecności atrybutów w .Net. Najpopularniejsze to metody IsDefined oraz GetCustomAttribute. Oczywiście drugą z nich można wykorzystać do sprawdzania atrybutu poprzez  porównanie zwracanej wartości z null'em. Poniżej prezentuję krótki kod porównujący wydajność obu rozwiązań.

    class Program
    {
        private static Type type = typeof(Test);

        private static Type attributeType = typeof(TestAttribute);

        private static void MeasureTime(Func<bool> action)
        {
            var watch = Stopwatch.StartNew();
            for(var i = 0; i < 1000; i++)
            {
                action ();
            }

            watch.Stop();

            Console.WriteLine(watch.ElapsedTicks);
        }

        static void Main()
        {
            RuntimeHelpers.PrepareMethod(typeof(Program).GetMethod("IsDefinded", BindingFlags.Public | BindingFlags.Static).MethodHandle);
            RuntimeHelpers.PrepareMethod(typeof(Program).GetMethod("GetCustomeAttributes", BindingFlags.Public | BindingFlags.Static).MethodHandle);

            MeasureTime(IsDefinded);
            MeasureTime(GetCustomeAttributes);
        }

        public static bool IsDefinded()
        {
            return type.IsDefined(attributeType, false);
        }

        public static bool GetCustomeAttributes()
        {
            return type.GetCustomAttribute(attributeType, false) != null;
        }
    }

    [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
    public sealed class TestAttribute : Attribute
    {
        private readonly string positionalString;

        public TestAttribute(string positionalString)
        {
            this.positionalString = positionalString;
        }

        public string PositionalString
        {
            get
            {
                return positionalString;
            }
        }

    }


    [TestAttribute("SomeText")]
    public class Test
    {
        
    }

Uruchamiając kod na testowej maszynie uzyskałem rezultaty 3.548 oraz 10.607. Widać wyraźnie, że różnica jest znaczna, co w przypadku przeglądania całego assebly pod kątem obecności typów posiadających dany atrybut może wyraźnie skrócić czas operacji.

Na koniec chciałbym wspomnieć o jeszcze jednej metodzie pozwalającej pobrać atrybut -GetCustomAttributesData. Jest ona o tyle przydatna, gdyż nie powoduje utworzenia instancji atrybutu, a pozwala na wygodne sprawdzenie jakie parametry są przekazywane do konstruktora i właściwości, ale o tym innym razem