如下代码示例一个单例模式的类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的私有构造函数还会被调用一次……这是什么问题?该如何解决呢?
{
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的私有构造函数还会被调用一次……这是什么问题?该如何解决呢?
{
Instance =new ServiceManager();
} public static ServiceManager Current { get { return Instance; } } }
public class ServiceManager
{
private static readonly ServiceManager Instance = new ServiceManager(); static ServiceManager()
{
Instance = new ServiceManager();
} public static ServiceManager Current
{
get
{
return Instance;
}
}
}
我使用Assembly.CreateInstance(typeof(B)).GetType.Assembly 获得的程序集与 typeof(B).Assembly 获得的程序集不一样(虽然我使用强名称,并且这两个程序集的Fullname看上去都一样),这是什么原因导致的?
B b = (B)a1.CreateInstance(typeof(B).FullName);
的确是这个问题,程序在启动时显示的加载了程序集(Assembly.Load(Byte[])方式),这样就导致了上述问题。虽然我找到了两个解决方案:
1:用另外一个AppDomain承载这些程序集
2:将程序集放置在程序根目录或者GAC中,然后通过Assembly.Load(AssemblyName)方式加载但这两个方案我暂时都不敢尝试:
第一种方案虽然最优雅并且最安全,可以说是组件框架一般的实现模式,但我手上的程序是基于MVVM模式设计的WPF程序,其中运用了大量的DataTemplate,并且Model直接声明了WCF的DataContact,我不知道也没有找到相关资料可以保证跨域封送不会对上述内容有影响,现在也没有时间去尝试。第二种方案可能会是我最终采用的,虽然它并不符合设计的初衷。不知道有没有关于第一种方法的资料?如能提供,不胜感激!
使用LoadFrom,不要使用LoadFile。如果你使用LoadFile,那么它就是两个重名的Assembly,两套重名的Type!
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时会出现问题。
你所说的“很明显地是另外加载一个Assembly了”具体如何理解?我这里具体的情况是这样的:
应用程序使用Assembly.Load(Byte[])的方式从内存中加载了一个程序集,然后将其中的一个类型实例化,并调用这个实例中的方法(将此处表示为A)
这个方法中实现一个ServiceHost,并将这个程序集中的另外一个类型B作为服务运行。问题就在这里,在A的上下文中创建一个B实例,与ServiceHost中B的实例做类型对比,得到的结果是不一样的类型.我猜想,应该内存中出现了同一程序集的两个副本,或者是有资料中描述的创建实例时应用了不同的上下文导致了实例类型不同。上述问题通过Assembly.Load(AssemblyName)就可以解决,但是否有可能在不改变加载方式(从内存中加载)的情况下解决此问题呢?
{ #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());
}
} }......
}