Czy istnieje sposób, aby wymusić załadowanie wszystkich odwołanych zestawów do domeny aplikacji?
Moje projekty są ustawione tak:
- Projekt "Definicja"
- Projekt "Realizacja"
- Projekt "Konsument"
Projekt "konsument" odwołuje się zarówno do "definicji", jak i "implementacji", ale nie odnosi się statycznie do żadnych typów w "implementacji".
Po uruchomieniu aplikacji Projekt "konsument" wywołuje statyczną metodę w "definicji", która musi znaleźć typy w"implementacji"
Czy Jest jakiś sposób, abym mógł wymusić jakiekolwiek assembly do załadowania do domeny aplikacji bez znajomości ścieżki lub nazwy, a najlepiej bez konieczności korzystania z pełnowartościowego frameworka IOC?
6 answers
To chyba zadziałało:
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
var loadedPaths = loadedAssemblies.Select(a => a.Location).ToArray();
var referencedPaths = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll");
var toLoad = referencedPaths.Where(r => !loadedPaths.Contains(r, StringComparer.InvariantCultureIgnoreCase)).ToList();
toLoad.ForEach(path => loadedAssemblies.Add(AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(path))));
Jak zauważył Jon, idealne rozwiązanie wymagałoby rekurencji w zależności dla każdego z załadowanych zespołów, ale w moim konkretnym scenariuszu nie muszę się tym martwić.
Update: The Managed Extensibility Framework (System.ComponentModel) zawarte w. Net 4 ma znacznie lepsze możliwości do realizacji takich rzeczy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-21 17:55:15
Możesz użyć Assembly.GetReferencedAssemblies
aby uzyskać AssemblyName[]
, a następnie wywołać Assembly.Load(AssemblyName)
na każdym z nich. Musisz oczywiście rekurencyjnie-ale najlepiej śledzić już załadowane zespoły:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-05 04:44:10
Chciałem podzielić się rekurencyjnym przykładem. Wywołuję metodę LoadReferencedAssembly w mojej rutynie startowej w następujący sposób:
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
this.LoadReferencedAssembly(assembly);
}
Jest to metoda rekurencyjna:
private void LoadReferencedAssembly(Assembly assembly)
{
foreach (AssemblyName name in assembly.GetReferencedAssemblies())
{
if (!AppDomain.CurrentDomain.GetAssemblies().Any(a => a.FullName == name.FullName))
{
this.LoadReferencedAssembly(Assembly.Load(name));
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-04 10:35:49
Jeśli używasz Fody.Costura, lub jakiekolwiek inne rozwiązanie łączące montaż, przyjęta odpowiedź nie będzie działać.
Poniższe ładuje odnośne zespoły dowolnego aktualnie załadowanego zespołu. Rekurencja jest pozostawiona Tobie.
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
loadedAssemblies
.SelectMany(x => x.GetReferencedAssemblies())
.Distinct()
.Where(y => loadedAssemblies.Any((a) => a.FullName == y.FullName) == false)
.ToList()
.ForEach(x => loadedAssemblies.Add(AppDomain.CurrentDomain.Load(x)));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-13 14:32:45
Ponieważ musiałem załadować assembly + dependencies z określonej ścieżki, napisałem do tego klasę.
public static class AssemblyLoader
{
private static readonly ConcurrentDictionary<string, bool> AssemblyDirectories = new ConcurrentDictionary<string, bool>();
static AssemblyLoader()
{
AssemblyDirectories[GetExecutingAssemblyDirectory()] = true;
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
}
public static Assembly LoadWithDependencies(string assemblyPath)
{
AssemblyDirectories[Path.GetDirectoryName(assemblyPath)] = true;
return Assembly.LoadFile(assemblyPath);
}
private static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
{
string dependentAssemblyName = args.Name.Split(',')[0] + ".dll";
List<string> directoriesToScan = AssemblyDirectories.Keys.ToList();
foreach (string directoryToScan in directoriesToScan)
{
string dependentAssemblyPath = Path.Combine(directoryToScan, dependentAssemblyName);
if (File.Exists(dependentAssemblyPath))
return LoadWithDependencies(dependentAssemblyPath);
}
return null;
}
private static string GetExecutingAssemblyDirectory()
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
var uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-12 04:50:08
Kolejna wersja (oparta na odpowiedzi Daniela Schaffera ) ma miejsce w przypadku, gdy nie trzeba wczytywać wszystkich zestawów, ale predefiniowaną ich liczbę:
var assembliesToLoad = { "MY_SLN.PROJECT_1", "MY_SLN.PROJECT_2" };
// First trying to get all in above list, however this might not
// load all of them, because CLR will exclude the ones
// which are not used in the code
List<Assembly> dataAssembliesNames =
AppDomain.CurrentDomain.GetAssemblies()
.Where(assembly => AssembliesToLoad.Any(a => assembly.GetName().Name == a))
.ToList();
var loadedPaths = dataAssembliesNames.Select(a => a.Location).ToArray();
var compareConfig = StringComparison.InvariantCultureIgnoreCase;
var referencedPaths = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll")
.Where(f =>
{
// filtering the ones which are in above list
var lastIndexOf = f.LastIndexOf("\\", compareConfig);
var dllIndex = f.LastIndexOf(".dll", compareConfig);
if (-1 == lastIndexOf || -1 == dllIndex)
{
return false;
}
return AssembliesToLoad.Any(aName => aName ==
f.Substring(lastIndexOf + 1, dllIndex - lastIndexOf - 1));
});
var toLoad = referencedPaths.Where(r => !loadedPaths.Contains(r, StringComparer.InvariantCultureIgnoreCase)).ToList();
toLoad.ForEach(path => dataAssembliesNames.Add(AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(path))));
if (dataAssembliesNames.Count() != AssembliesToLoad.Length)
{
throw new Exception("Not all assemblies were loaded into the project!");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-05 17:25:44