對象緩衝實現

來源:互聯網
上載者:User

有這麼一種情境,對於某個指定的介面,你需要得到它的一個執行個體,首先你從一個緩衝中取,如果有就返回,否則調用一個指定的 delegate 來得到這個執行個體。假設有介面和實現:

    public interface IBar { }    public class Bar : IBar {        public string Name { get; private set; }        public Bar(string name) {            this.Name = name;        }    }    public class TestBar : IBar {     }

 

我希望通過某種方式來擷取對象, 如果有緩衝(假設一個TestBar的對象)就取它,否則 new Bar(“Hello”):

    Cache.Get<IBar>("Hello");

 

我的第一個實現採用了一個Dictionary, 緩衝了Type –> Object + Delegate 對:

    public static class DictCache    {        private class CachedObj        {            public object Instance { get; set; }            public Delegate Callback { get; set; }        }        private static IDictionary<Type, CachedObj> cache = new Dictionary<Type, CachedObj>();        public static T Get<T>(params object[] arguments)        {            CachedObj pair;            if (!cache.TryGetValue(typeof(T), out pair))            {                throw new InvalidOperationException();            }            return (T)(pair.Instance ?? pair.Callback.DynamicInvoke(arguments));        }        public static void Set<T>(object instance, Expression<Func<T>> exp)        {            SetMapping<T>(instance, exp);        }        public static void Set<P, T>(object instance, Expression<Func<P, T>> exp)        {            SetMapping<T>(instance, exp);        }        public static void Set<T>(object instance, LambdaExpression exp)        {            SetMapping<T>(instance, exp);        }        private static void SetMapping<T>(object instance, LambdaExpression exp)        {            cache[typeof(T)] = new CachedObj { Instance = instance, Callback = exp.Compile() };        }    }

 

在這個實現裡,主要利用了Delegate來延遲建立對象,重載Set 方法是為了方便。

 

首先我們可以緩衝這個對象:

            DictCache.Set<string, IBar>(new TestBar(), name => new Bar(name));

 

然後取用:

            IBar bar = DictCache.Get<IBar>("Hello");

 

考慮到在這個實現中使用 Delegate 的 DynamicInvoke 方法,可能會有一些Performance 問題,我的第二個方法使用靜態類,並且把Delegate作為型別參數:

    public static class StaticCache    {        private static class Cached<T, TDelegate>        {            public static T Instance { get; set; }            public static TDelegate Callback { get; set; }        }        public static T Get<T>() where T : class        {            return (T) (Cached<T, Func<T>>.Instance ?? Cached<T, Func<T>>.Callback());        }        public static T Get<P, T>(P p) where T : class        {            return (T)(Cached<T, Func<P, T>>.Instance ?? Cached<T, Func<P, T>>.Callback(p));        }        public static void Set<T>(T instance, Expression<Func<T>> exp)        {            SetMapping<T, Func<T>>(instance, exp);        }        public static void Set<P, T>(T instance, Expression<Func<P, T>> exp)        {            SetMapping<T, Func<P, T>>(instance, exp);        }        public static void SetMapping<T, TDelegate>(T instance, Expression<TDelegate> exp)        {            Cached<T, TDelegate>.Instance = instance;            Cached<T, TDelegate>.Callback = exp.Compile();        }    }

 

這個方案,效率上會有提高,但是需要更多的Get 和 Set 的重載,以針對不同的參數類型和個數, 用法如下:

            StaticCache.Set<string, IBar>(null, name => new Bar(name));

 

擷取:

            IBar bar = StaticCache.Get<string, IBar>("name");

 

是否還有其他的更簡單的方法呢?發揮我們的創造力!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.