2009-01-21 24 views
5

Aşağıdaki kod ile bazı sorunlar yaşıyorum:Type.IsSubclassOf(), AppDomains genelinde çalışmıyor mu?

private class ClientPluginLoader : MarshalByRefObject 
{ 
    public bool IsPluginAssembly(string filename) 
    { 
     AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomainReflectionOnlyAssemblyResolve); 

     Assembly asm = Assembly.ReflectionOnlyLoadFrom(filename); 

     Type[] types = asm.GetTypes(); 
     foreach (Type type in types) 
     { 
      if (type.IsSubclassOf(typeof(ClientPlugin))) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 
} 

kod benim özel uygulama etki alanının CreateInstanceFromAndUnwrap aracılığıyla oluşturduğunuz bir proxy üzerinden denir(). Bu, özel uygulama alanımın bağlamında IsPluginAssembly() yürütüldüğü anlamına gelir.

Sorun, IMHO'nun true olarak geri dönmesine rağmen IsSubclassOf() çağrısının her zaman false döndürmesidir. Söz konusu "tip", ClientPlugin'den gerçekten miras alıyor - bundan şüpheniz yok.

İstemciPlugin, yukarıdaki kod parçasında açıkça görüldüğü gibi el ile çözdüğüm farklı bir özel derlemede tanımlanır.

Ben yanlış olduğu bu ifadeyi if (type.IsSubclassOf(...)) satırda kesme noktası koymak ve teyit ettik:

type.BaseType == typeof(ClientPlugin) 

Öte yandan, bu ifade doğru:

type.BaseType.FullName == typeof(ClientPlugin).FullName 

Bu nasıl mümkün olabilir ? Neler oluyor?

GÜNCELLEME: Kent Boogaart beni doğru yöne işaret etti. İnterneti biraz daha araştırdım ve this blog yayına girdim. Bunu yapmak için Load/LoadFrom/ReflectionOnlyLoadFrom çakışmalarımı çözmem gerekiyor gibi görünüyor.

cevap

7

Bu, farklı bir içeriğe yüklenmesinden kaynaklanmaktadır. Bir yüklemeyi yükleme (Load/LoadFrom/ReflectionOnlyLoad) hangi içeriğin yüklendiğini belirler.

using System; 
using System.Reflection; 

class Foo 
{ 
    public static void Main() 
    { 
     var type = typeof(Foo); 
     var reflectionLoadType = Assembly.ReflectionOnlyLoad("ConsoleApplication1").GetType("Foo"); 
     Console.WriteLine(type == reflectionLoadType); //false 
     Console.WriteLine(type.Equals(reflectionLoadType)); //false 

     Console.WriteLine("DONE"); 
     Console.ReadKey(); 
    } 
} 

fazla bilgi için here bakınız: Bu basit örnek de sorunu gösterir.

2

Benzer bir sorun yaşadım. Ayrıca bu mimariye sahiptim - ClientPlugin temel sınıfını içeren bir .DLL; bu .DLL'ye başvuran birkaç eklenti; ve aynı zamanda bu .DLL'ye referans veren bir ana uygulama. Sorun, ClientPlugin temel sınıfıyla .DLL'nin iki klasörde (hem Eklentiler klasörü hem de ana uygulama klasörü) kopyalanmasıydı. Böylece AppDoma'mda iki kere yüklendi (eklentiler de dolaylı olarak yüklendi). Ve ana uygulama yansıtma türü büyü yapmaya çalıştığında, başarısız oldu, çünkü ClientPlugin türünün iki örneği vardı.

Bunun tam olarak sizin durumunuz olduğunu düşünmüyorum da, burada hala öğrenilecek bir ders var - bir .DLL iki kez yüklenirse, türler de çoğaltılacak. Sizin durumunuzda ya ayrı AppDomains veya "ReflectionOnlyLoad" olduğundan şüphelenirim, çünkü .DLL bir şekilde farklı şekilde yüklenir.

+0

Tam olarak bu sorun vardı, iki klasörde aynı DLL'nin iki kopyasını vardı. "IsSubclassOf" el ile çalıştırıldığında, bu hata iletisini aldım: 'ServiceCore.BaseService' türü 'ServiceCore.dll' ve 'ServiceCore.dll' hem de var – vpalmu