首页 > 其他 > 详细

单实例使用探讨

时间:2014-02-14 04:46:54      阅读:284      评论:0      收藏:0      [点我收藏+]

单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点。

一般使用情况:

bubuko.com,布布扣
        private static readonly object _lockObj = new object();
        private static TargetObject_instance;

        /// <summary>
        /// Get 唯一实例
        /// </summary>
        public static TargetObject Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lockObj)
                    {
                        if (_instance == null)
                            _instance = new TargetObject();
                    }
                }

                return _instance;
            }
        }
bubuko.com,布布扣

这样就能保证在多线程模式下,只能使用一个实例了。

但是这样子不便于拓展,每次新增一个类就要多加一个单实例,很不方便,于是就想到了原先介绍使用的MEF,把每个单实例都看成是一个插件使用,标记后,然后初始化的时候,实例化这些实例,放到相对应的容器中。对应用层只提供从容器中捞取的实例。

想法了然后就是实践了:

1 定义单实例的Attribute

bubuko.com,布布扣
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    public class PartAttribute : Attribute
    {
    }
bubuko.com,布布扣

 

2 单实例中初始化后,可能需要处理的事件,因为单实例作为插件使用,一般都是使用无参的构造函数,进行反射实例,必然有些属性无法正常加载,必须要读取配置,或者进行其他处理,所以就要执行单实例类中初始化的事件,这样就需要单独标记MethodAttribute了以区分各类方法,因此第二件事定义MethodAttribute。

bubuko.com,布布扣
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
    public sealed class PartActivationMethodAttribute : Attribute
    {
    }
bubuko.com,布布扣

 

3 定义容器,存放各类单实例。

bubuko.com,布布扣
public sealed class PartContainer
    {
         internal IDictionary<Type, PartMetadata> PartInformation { get; set; }
         public void Initialize(IEnumerable<Assembly> partAssemblies)
        {
         }

        public void Activate()
        {
         }
    }
bubuko.com,布布扣

 

4定义初始化方法,查找已标记PartAttribute的Assembly

bubuko.com,布布扣
public void Initialize(IEnumerable<Assembly> partAssemblies)
        {
            var partInformation = from asm in partAssemblies
                                  from type in asm.GetTypes()
                                  where type.IsDefined(typeof(PartAttribute), false)
                                  select new
                                  {
                                      Type = type,
                                      Metadata = PartMetadata.GetPartMetadata(type)
                                  };
            PartInformation = partInformation.ToDictionary(p => p.Type, p => p.Metadata);

        }
bubuko.com,布布扣

 

5定义激活方法,调用已标记MethodAttribute的Method

bubuko.com,布布扣
public void Activate(IPartActivationContext configuration = null)
        {
            // 整理可以激活的插件类型
            var activePartsInfomation = new Dictionary<Type, PartMetadata>();
            foreach (var partInfo in PartInformation)
            {
                var type = partInfo.Key;
                var metadata = partInfo.Value;
                if (configuration == null || configuration.IsPartEnabled(type, metadata))
                {
                    activePartsInfomation[type] = metadata;
                }
            }

            // 激活插件
            ActiveParts.ForEach(p => OperateActivation<PartActivationMethodAttribute>(p));
        }

private void OperateActivation<OperationType>(object partInstance)
        {
                 // 根据Attribute找到方法
            var methodInfo = partInstance.GetType()
                .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                .Where(m => m.IsDefined(typeof(OperationType), false))
                .ToArray();

            if (methodInfo.Length == 0)
                return;

            if (methodInfo.Length != 1)
                throw new PartException(string.Format("重复的部件{0}方法", operationName));

            var activationMethod = methodInfo[0];
            var methodParameters = activationMethod.GetParameters();
            if (methodParameters != null && methodParameters.Length != 0)
                throw new PartException(string.Format("部件{0}方法不应该包含任何参数", operationName));
            methodInfo[0].Invoke(partInstance, null);
        }
bubuko.com,布布扣

 

然后就可以在目标实力类中使用了:

bubuko.com,布布扣
    [Part]
    internal class TargetObject : ITargetObject 
    {
         [PartActivationMethod]
        private void Initialize()
        {
        }
    }
bubuko.com,布布扣

 

使用顺序:

定义一个PartContainer partContainer

调用partContainer.Initialize(targetObjectAssemblie);

调用partContainer.Activate();

最后就能在partContainer.ActiveParts中获取自己想要的Targerobject实例了。

单实例使用探讨

原文:http://www.cnblogs.com/gavinhuang/p/3548127.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!