如下代码示例一个单例模式的类public class ServiceManager
    {
        private static readonly ServiceManager Instance = new ServiceManager();        private ServiceManager() { }        public static ServiceManager Current
        {
            get
            {
                return ServiceManager.Instance;
            }
        }
    }public class B
   {
        public B()
        {
               var Current=ServiceManager.Current;
        } 
   }
如果我通过 var B=new B() 创建 B 实例的话一切正常,ServiceManager只有一个实例但如果我通过 Assembly.CreateInstance(typeof(B).FullName) 创建 B 实例的话就会和预期的不一样,ServiceManager的私有构造函数还会被调用一次……这是什么问题?该如何解决呢?

解决方案 »

  1.   

    改成这样: 这才是单例模式c#标准实现方式,public class ServiceManager    {        private static readonly ServiceManager Instance = null;         private ServiceManager() { }static ServiceManager()
    {
    Instance =new ServiceManager();
    }         public static ServiceManager Current        {            get            {                return Instance;            }        }    }
      

  2.   


    public class ServiceManager
            {
                private static readonly ServiceManager Instance = new ServiceManager();             static ServiceManager()
                {
                    Instance = new ServiceManager();
                }            public static ServiceManager Current
                {
                    get
                    {
                        return Instance;
                    }
                }
            }
      

  3.   

    我发现关键问题不是单例类的代码有问题,而是这个程序集是使用Assembly.Load(Byte[])方法动态加载的,
    我使用Assembly.CreateInstance(typeof(B)).GetType.Assembly 获得的程序集与 typeof(B).Assembly 获得的程序集不一样(虽然我使用强名称,并且这两个程序集的Fullname看上去都一样),这是什么原因导致的?
      

  4.   

    [A]Carefree.Component.ServiceHost.Model.ServiceManager 无法强制转换为 [B]Carefree.Component.ServiceHost.Model.ServiceManager。类型 A 源自“Carefree.Component.ServiceHost, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f25efbbe7bbb9267”(在字节数组的上下文“LoadNeither”中)。类型 B 源自“Carefree.Component.ServiceHost, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f25efbbe7bbb9267”(在字节数组的上下文“LoadNeither”中)。
      

  5.   

    private ServiceManager()//每次都会调用private static ServiceManager()//只调用一次如楼上各位所说的,你的单例模式写错了~static的才对~
      

  6.   

    你这是一个基于插件的程序吧?你那个有冲突的dll是不是被load了两次?
      

  7.   

    好吧。我觉得事情的真相应该是这样的:你应该有两个工程,一个是主工程A和另一个副工程A1(也就是你的类B和ServiceManager所在的工程)。现在你是不是想在A中加载A1的dll,动态的创建类B?如果是这样,你是不是在工程A的Reference中加入了工程A1?如果还是这样,你是不是还在A中某处用Assembly.LoadFile来加载了A1的dll。如果是这样,那你应该会遇到你提到的问题。如果上面的场景描述正确,lz得到7楼异常的原因是因为调用了下面这段代码吧?Assembly a1 = Assembly.LoadFile(path);//The path of A1.dll
    B b = (B)a1.CreateInstance(typeof(B).FullName);
      

  8.   


    的确是这个问题,程序在启动时显示的加载了程序集(Assembly.Load(Byte[])方式),这样就导致了上述问题。虽然我找到了两个解决方案:
    1:用另外一个AppDomain承载这些程序集
    2:将程序集放置在程序根目录或者GAC中,然后通过Assembly.Load(AssemblyName)方式加载但这两个方案我暂时都不敢尝试:
    第一种方案虽然最优雅并且最安全,可以说是组件框架一般的实现模式,但我手上的程序是基于MVVM模式设计的WPF程序,其中运用了大量的DataTemplate,并且Model直接声明了WCF的DataContact,我不知道也没有找到相关资料可以保证跨域封送不会对上述内容有影响,现在也没有时间去尝试。第二种方案可能会是我最终采用的,虽然它并不符合设计的初衷。不知道有没有关于第一种方法的资料?如能提供,不胜感激!
      

  9.   


    使用LoadFrom,不要使用LoadFile。如果你使用LoadFile,那么它就是两个重名的Assembly,两套重名的Type!
      

  10.   

    lz你在这里可能有一个误区。用我之前的工程A和工程A1的例子继续说明。如果我没猜错,你在A中引用A1是为了使用类B,这实际上是在编译时就决定了工程A对于类B的依赖。但是从一个标准的组件系统来说,工程A在编译时并不能对具体的类B依赖,而是应该对类B的抽象产生依赖。程序集AAssembly a1 = Assembly.LoadFile(path);//path is the filepath of A1.dll
    BaseB b = (BaseB)a1.CreateInstance(typeName);//typeName is the name of class B
    程序集A1public class B:BaseB{}
    程序集A2public abstract BaseB{}
    程序集A和程序集A1都引用了程序集A2。这样你在A中就可以去掉对程序集A1的引用,从而就不会出现你现在的问题。
    当然还有一点要注意,在A中调用Assembly.Load方法加载包含有ViewModel的dll时,一定要保证只加载一次哦,否则View在寻找绑定的ViewModel时会出现问题。
      

  11.   

    http://bbs.csdn.net/topics/370248412
      

  12.   

    Assembly.Load稍微复杂,它有好多种形式。你应该选择正确的形式——内部调用LoadFromAssemblyName——的形式。而你的形式,很明显地是另外加载一个Assembly了!可能有人没有想到内存中会有重名的Assembly、重名的Type,所以没有想到需要深入去了解Load。
      

  13.   


    你所说的“很明显地是另外加载一个Assembly了”具体如何理解?我这里具体的情况是这样的:
    应用程序使用Assembly.Load(Byte[])的方式从内存中加载了一个程序集,然后将其中的一个类型实例化,并调用这个实例中的方法(将此处表示为A)
    这个方法中实现一个ServiceHost,并将这个程序集中的另外一个类型B作为服务运行。问题就在这里,在A的上下文中创建一个B实例,与ServiceHost中B的实例做类型对比,得到的结果是不一样的类型.我猜想,应该内存中出现了同一程序集的两个副本,或者是有资料中描述的创建实例时应用了不同的上下文导致了实例类型不同。上述问题通过Assembly.Load(AssemblyName)就可以解决,但是否有可能在不改变加载方式(从内存中加载)的情况下解决此问题呢?
      

  14.   

    为什么需要在A中创建一个B的实例呢?如果B是一个服务提供类,是否可以通过接口对外暴露相应的功能?这样在A中就不需要显示实例化B了。
      

  15.   

    比如类BudgetClass: public partial class BudgetClass
        {        #region GetInstance
            private static readonly object LockHelper = new object();
            private static BudgetClass _instance;
            public static BudgetClass Instance
            {
                get
                {
                    lock (LockHelper)
                    {
                        return _instance ?? (_instance = new BudgetClass());
                    }
                }        }......
    }