2011-06-27 30 views
6

Tôi đã tạo ra một thư viện kiểm trabóng sao chép để không khóa lắp ráp

public class Test 
{ 
    public int Add(int val1, int val2) 
    { 
     return val1 + val2; 
    } 
} 

Và một dự án để gọi nó là:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 
using System.IO; 

namespace Loader 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      String path = @"...Lib.dll"; // path to lib 
      var name = Path.GetFileName(path); 

      AppDomainSetup setup = new AppDomainSetup 
      { 
       ApplicationBase = @"...", // directory where Lib.dll is 
       ShadowCopyFiles = "true", 
       ShadowCopyDirectories = @"..."// directory where Lib.dll is 
      }; 

      var appdomain = AppDomain.CreateDomain("Loader." + name, null, setup); 
      Assembly ass = Assembly.LoadFile(path); // <--- I think here is the problem, here where assembly is locked 
      Assembly assembly = appdomain.Load(ass.FullName); 

      dynamic a = assembly.CreateInstance("Lib.Test"); 

      Console.WriteLine(a.Add(1, 5)); 
     } 
    } 
} 

Xin giúp tìm thấy những gì tôi đã làm sai? Tại sao lắp ráp của tôi bị khóa?

EDIT: với tên lắp ráp hardcoded:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 
using System.IO; 

namespace Loader 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AppDomainSetup ads = new AppDomainSetup(); 

      String fullPath = @"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Lib.dll"; 

      ads.ShadowCopyFiles = "true"; 
      ads.ApplicationName = "AppName"; 
      ads.ShadowCopyDirectories = Path.GetDirectoryName(fullPath); 
      //ads.ApplicationBase = Path.GetDirectoryName(fullPath); 
      //ads.PrivateBinPath = Path.GetDirectoryName(fullPath); 
      ads.CachePath = @"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Cache\"; 

      AppDomain ad = AppDomain.CreateDomain("myName" + ads.ApplicationName, null, ads); 

      ad.AssemblyResolve += new ResolveEventHandler(ad_AssemblyResolve); 

      Console.WriteLine(ad.ShadowCopyFiles); 
      Console.WriteLine(ad.SetupInformation.ShadowCopyDirectories); 

      try 
      { 
       //Assembly assembly = ad.Load(AssemblyName.GetAssemblyName(fullPath)); 
       //dynamic obj = ad.CreateInstanceAndUnwrap(assembly.GetName().Name, "Lib.Test"); 

       dynamic obj = ad.CreateInstanceAndUnwrap("Lib", "Lib.Test"); 

       Console.WriteLine(obj.Add(1, 7)); 

       Console.ReadKey(); 

       Console.WriteLine(obj.Add(1, 90)); 
      } 
      catch(Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
     } 

     static Assembly ad_AssemblyResolve(object sender, ResolveEventArgs args) 
     { 
      return Assembly.LoadFile(@"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Lib.dll"); 
     } 
    } 
} 

Điều thú vị là cache assebly cũng bị khóa.

EDIT 2:

Đây là dòng mã để ngăn chặn việc lắp ráp

Console.WriteLine(obj.Add(1, 7)); 

Vì vậy, một khi một phương pháp trong Lib.Test được truy cập các assenbly bị chặn.

Giải pháp có thể là gì?

+0

Vui lòng đăng lỗi chính xác mà bạn đang nhận được. –

+0

Vấn đề chính xác như tôi đã nói là Lib.lắp ráp dll bị khóa. Ví dụ tôi không thể phát lại khi ứng dụng đang chạy. – NDeveloper

+0

Bạn cần sử dụng giao diện trong phiên bản thứ 3 để ngăn mã của bạn tải loại được xây dựng vào tên miền ứng dụng chính. Không sử dụng LoadFile. –

Trả lời

0

Bạn có hai tùy chọn, bạn cần phải tra cứu tên lắp ráp trước khi chạy và mã hóa cứng hoặc nếu bạn không biết thời gian chạy trước đó, bạn cần viết thư viện thứ hai mà bạn biết FullName và tải nó trong AppDomain. Thư viện thứ hai sẽ là một lớp có một chức năng

public Assembly GetAssemblyForOtherAppDomain(string path) 
{ 
    return Assembly.LoadFile(path) 
} 

Điều này sẽ tải mục tiêu của bạn trong AppDomain mới mà không khóa nó, nên mở nó bằng bản sao ẩn.

EDIT: vì sao phương pháp của bạn không làm việc, bạn nơi đúng về tải mà khóa nó và once a assembly is loaded in to a AppDomain it can not be unloaded.

+0

Tất nhiên tôi biết tên lắp ráp ... nhưng nó sẽ không Cứu giúp. Tôi đã thử ... cùng một vấn đề. – NDeveloper

+0

Vui lòng kiểm tra câu hỏi được cập nhật bằng mã mới. – NDeveloper

1

Bạn đang tải lắp ráp vào AppDomain chính của bạn khi bạn chạy Assembly.LoadFile(), mà khóa tập tin. Nếu bạn muốn tải nó trực tiếp vào AppDomain, bạn cần sử dụng trực tiếp AppDomain.Load(), cho phép AppDomain giải quyết nó dựa trên các tham số bạn đã chỉ định. Lưu ý rằng, vì assembly không được nạp trong AppDomain chính của bạn, loại đó không thể truy cập được từ phương thức Main của bạn. Lib.Test bạn sẽ cần phải xuất phát từ MarshalByRefObject để hệ thống marshalling có thể tạo một proxy (trong đó tiếp tục được gói gọn trong một proxy động khi bạn gán nó vào động.)


EDIT:

Khi suy nghĩ thêm, tôi nghi ngờ vấn đề ở đây là, để gọi phương thức trên proxy động, nó phải phản ánh trên đối tượng (chính nó là một proxy minh bạch cho cá thể trong AppDomain khác của bạn.) Nếu nó kết thúc phản ánh trên kiểu lớp gốc (và không phải là loại proxy trong suốt 'ẩn'), điều này sẽ khiến cho nó tải một bản sao của assembly trong AppDomain cục bộ (do đó khóa nó.) Đây là một trong những lý do tại sao, khi sử dụng AppDomain isolat ion, bạn thường truyền đối tượng đến một giao diện được xác định trong một hội đồng riêng biệt mà cả ứng dụng 'chính' và AppDomain được lưu trữ có thể tham chiếu. Họ sẽ nhận được bản sao của riêng họ về lắp ráp giao diện được tải, nhưng bây giờ lắp ráp 'triển khai' được phân lập.

+0

Vui lòng xem mã đã chỉnh sửa ... không có Assembly.LoadFile. Ngoài ra tôi có nguồn gốc Lib.Test từ MarshalByRefObject và thiết lập [Serializable], nhưng vẫn như cũ .... Tôi không thể tưởng tượng những gì tôi cần phải làm khác. – NDeveloper

+0

@NDeveloper, trong trường hợp mới này, bạn đang buộc AppDomain giải quyết Hội bằng cách gọi LoadFile, bỏ qua việc sao chép bóng và tải tệp trực tiếp. Nếu bạn muốn nó tải các tập tin bằng cách sử dụng cơ chế sao chép bóng tối, bạn cần phải vượt qua FullName của hội đồng để CreateInstanceAndUnwrap và cho phép AppDomain để làm độ phân giải tập tin riêng của mình. –

+0

Nhưng ad_AssemblyResolve không bao giờ được gọi, vì vậy mọi thứ như bạn đã mô tả. – NDeveloper

Các vấn đề liên quan