编程语言
首页 > 编程语言> > c#-这是在方法和类上创建和使用自定义属性的正确方法吗?

c#-这是在方法和类上创建和使用自定义属性的正确方法吗?

作者:互联网

今天晚上我一直在研究自定义属性,以查看是否可以简化缓存层.我想出了以下几点:

namespace AttributeCreationTest
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
    public class Cache : Attribute
    {
        public Cache()
        {
            Length = "01h:30m";
        }

        public string Length;
    }

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class CacheIdentifier : Attribute
    {
    }


    [Cache]
    class Class1
    {
        [CacheIdentifier]
        public int ID { get; set; }
    }

    class Class2
    {
        [CacheIdentifier]
        public bool ID { get; set; }
    }

    [Cache(Length = "01h:10m")]
    class Class3
    {
        [CacheIdentifier]
        public string ID { get; set; }
    }

    class Program
    {

        static void Main(string[] args)
        {
            var f1 = new Class1 { ID = 2 };
            var f2 = new Class2 { ID = false };
            var f3 = new Class3 { ID = "someID" };

            DoCache(f1);
            DoCache(f2);
            DoCache(f3);
        }

        public static void DoCache(object objectToCache)
        {
            var t = objectToCache.GetType();

            var attr = Attribute.GetCustomAttribute(t, typeof(Cache));

            if (attr == null) return;

            var a = (Cache)attr;
            TimeSpan span;

            if (TimeSpan.TryParse(a.Length.Replace("m", "").Replace("h", ""), out span))
            {
                Console.WriteLine("name: {0}, {1}", t.Name, span);

                ExtractCacheData(objectToCache);

                return;
            }

            throw new Exception(string.Format("The Length value of {0} for the class {1} is invalid.", a.Length, t.Name)); 
        }

        public static void ExtractCacheData(object o)
        {
            var t = o.GetType();

            foreach (var prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                if (Attribute.IsDefined(prop, typeof(CacheIdentifier)))
                {
                    Console.WriteLine("   type: {0}, value {1}", prop.PropertyType, prop.GetValue(o));
                    break;
                }

                throw new Exception(string.Format("A CacheIdentifier attribute has not been defined for {0}.", t.Name));
            }
        }

    }
}

“缓存”属性将充实,但在学习C#领域时,我将其保留为最小.我的想法是允许对项目进行更轻松的缓存,包括一种简化的方法,该方法指定了缓存对象的时间.

这样看起来还好吗?使用这种模式将项目推送到缓存中是否会对性能产生重大影响?

我还没有找到任何详细介绍这种想法的教程,因此请多多指教.

解决方法:

您的实现似乎很好,但是CacheAttribute对象将针对每个属性声明而不是针对Class1对象.换句话说,创建多少个对象都没有关系-如果属性仅被分配一次-具有Length属性的该属性的对象在clr中将仅为一个.

但是,为什么不希望将某些接口传递给DoCache方法,您将定义一些接口来从对象检索CacheIdentifier?这样的实现将更加健壮,准确,可读.当然,您需要在每个类中实现它-但是在不指定任何职责的情况下,将对象传递给DoCache不会带来很多好处.对于用户而言,此API不直观且难以理解.

还有一点,如果您愿意的话,它会更高级-为了缓存的目的,我建议总体上看面向方面的编程,尤其是PostSharp.这篇文章5 Ways That Postsharp Can SOLIDify Your Code: Caching为实现缓存方面提供了一个很好的案例.简而言之,PostSharp还使用属性并通过IL编织在编译的第二步插入缓存行为

编辑:如果您想要一个漂亮且干净的模型而没有非域元素的任何失真,我建议另一种AOP技术,称为动态拦截.最受欢迎的框架是LinFuCastle Dynamic Proxy.结果,将通过构造函数指定依赖项,并且在解决这些依赖项时,IoC容器将创建代理.但是关键是,这些模型对这些代理一无所知,并将在简单对象在那里使用它们.这有点类似于Decorator pattern

标签:custom-attributes,c,net
来源: https://codeday.me/bug/20191031/1975749.html