我在.NET中搜索了很多關於在運行時重裝程序集的信息。我能找到的唯一方法是使用另一個AppDomain。但是這使事情變得非常複雜。在我的情況下幾乎是不可能的,因爲將在運行時加載的程序集中的類不會從MarshalByRefObject繼承。我看過Unity遊戲引擎。編輯器在運行時構建組件,並使用編譯後的程序集。這怎麼可能?.net在運行時重裝程序集
回答
一般而言,您不能在同一個AppDomain中裝配重新加載程序集。你可以動態地創建一個並加載它(它會永遠駐留在你的AppDomain中),你可以加載另一個幾乎不是完全相同的程序集副本,但是一旦程序集在AppDomain中,它就會被卡住。
想象一下,庫程序集定義了SomeType並且您的客戶端代碼剛剛創建了一個實例。如果卸載庫,該實例應該發生什麼?如果該庫位於另一個AppDomain中,則客戶端將使用具有定義良好的(在MarshalByRefObject中)行爲的代理(與域卸載並引發異常foreverafter)。支持任意類型的卸載會使運行時非常複雜,不可預知或者兩者兼而有之。
至於Unity,請參閱this discussion。 Quote:
一個「組裝reaload」聽起來像某種快速更新檢查,但實際上整個腳本環境重新加載。這將破壞管理土地上的一切。通過使用它的序列化系統,Unity可以從中恢復。 Unity在重裝之前序列化整個場景,然後重新創建所有場景並反序列化場景。當然,只有可以序列化的東西才能「存活」這個過程。
我已經完成了這個使用MEF。我不確定它是否適合您,但它運作良好。但是即使是MEF,它也有些複雜。
在我的情況下,我從一個特定的文件夾加載所有的DLL。
這些是設置類。
public static class SandBox
{
public static AppDomain CreateSandboxDomain(string name, string path, SecurityZone zone)
{
string fullDirectory = Path.GetFullPath(path);
string cachePath = Path.Combine(fullDirectory, "ShadowCopyCache");
string pluginPath = Path.Combine(fullDirectory, "Plugins");
if (!Directory.Exists(cachePath))
Directory.CreateDirectory(cachePath);
if (!Directory.Exists(pluginPath))
Directory.CreateDirectory(pluginPath);
AppDomainSetup setup = new AppDomainSetup
{
ApplicationBase = fullDirectory,
CachePath = cachePath,
ShadowCopyDirectories = pluginPath,
ShadowCopyFiles = "true"
};
Evidence evidence = new Evidence();
evidence.AddHostEvidence(new Zone(zone));
PermissionSet permissions = SecurityManager.GetStandardSandbox(evidence);
return AppDomain.CreateDomain(name, evidence, setup, permissions);
}
}
public class Runner : MarshalByRefObject
{
private CompositionContainer _container;
private DirectoryCatalog _directoryCatalog;
private readonly AggregateCatalog _catalog = new AggregateCatalog();
public bool CanExport<T>()
{
T result = _container.GetExportedValueOrDefault<T>();
return result != null;
}
public void Recompose()
{
_directoryCatalog.Refresh();
_container.ComposeParts(_directoryCatalog.Parts);
}
public void RunAction(Action codeToExecute)
{
MefBase.Container = _container;
codeToExecute.Invoke();
}
public void CreateMefContainer()
{
RegistrationBuilder regBuilder = new RegistrationBuilder();
string pluginPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
_directoryCatalog = new DirectoryCatalog(pluginPath, regBuilder);
_catalog.Catalogs.Add(_directoryCatalog);
_container = new CompositionContainer(_catalog, true);
_container.ComposeExportedValue(_container);
Console.WriteLine("exports in AppDomain {0}", AppDomain.CurrentDomain.FriendlyName);
}
}
這裏是實際的代碼。
AppDomain domain = SandBox.CreateSandboxDomain($"Sandbox Domain_{currentCount}", directoryName, SecurityZone.MyComputer);
foreach (FileInfo dll in currentDlls)
{
string path = Path.GetFullPath(Path.Combine(directoryName, dll.Name));
if (!File.Exists(path))
File.Copy(dll.FullName, Path.Combine(directoryName, dll.Name), true);
domain.Load(typeof(Runner).Assembly.FullName);
}
您可以通過這樣做來取回域名。
Runner runner = (Runner) domain.CreateInstanceAndUnwrap(typeof(Runner).Assembly.FullName, typeof(Runner).FullName);
runner.CreateMefContainer(); // or runner.Recompose();
您需要像這樣調用您的代碼。
runner.RunAction(() =>
{
IRepository export = MefBase.Resolve<IRepository>();
export?.Get("123");
Console.WriteLine("Executing {0}", export);
});
不知道這是否會在Unity中工作,但看起來很有前途! – PassetCronUs
- 1. 運行時的.NET程序集信息
- 2. 裝飾.NET程序集
- 3. 部署和運行.NET程序集
- 4. 從PowerShell運行.Net程序集的App.config
- 5. 在其他運行時編譯程序集Rreference運行時編譯程序集
- 6. 在.NET中創建安裝程序包運行時
- 7. 在運行時找不到引用的.Net程序集
- 8. 在運行時用.NET替換程序集
- 9. .NET在運行時加載程序集再次
- 10. 在運行時更改.Net程序集名稱
- 11. 在運行時枚舉.NET程序集資源
- 12. c#SmartDevice Cab安裝程序包含.net運行時安裝程序
- 13. NET Core安裝運行時
- 14. .NET 2.0程序集可以在.NET 4.0下運行嗎?
- 15. .Net重新排序DataGridView運行時列
- 16. 應用程序安裝在運行時
- 17. 在運行時修改程序集?
- 18. 在運行時加載的程序集
- 19. 在運行時加載程序集
- 20. 哪個.NET運行時是我在COM +中使用的.NET程序集?
- 21. 如何在.NET 4.0應用程序中運行.NET 2.0程序集
- 22. 運行Roslyn腳本時未在運行時發現程序集
- 23. 從vb6調用.net程序集導致運行時錯誤424
- 24. .net運行時試圖使用程序集的錯誤版本
- 25. .NET運行時如何找到非強名稱的程序集?
- 26. .Net:加載程序集時運行代碼
- 27. 運行時的.NET程序集初始化
- 28. 運行程序集的.NET調度程序?
- 29. Rasperry pi在運行程序時重啓
- 30. .net 3.5應用程序是否可以在安裝了.Net 2.0運行時的機器上運行?
好。我已經完成了你在第一段中所說的話。我使用一個字節數組加載程序集。我可以使用相同的信息加載另一個程序集。但問題是另一個程序集仍在內存中。需要多少內存?如果不可能,團結如何做到這一點?它是否將舊程序集保存在內存中? – KooKoo
請參閱上面 - Unity不會這樣做,它只是假裝:) – archnae
[您可以從一個單獨的域加載/卸載程序集](https://stackoverflow.com/questions/658498/how-to-load-an - 裝配到應用程序域與 - 所有引用遞歸)。 –