सिस्टम की आवश्यकताओं में से एक जो मैं विकसित करने में मदद कर रहा हूं वह फाइल आयात करने की क्षमता है और हमारे पास विभिन्न प्रकार की फ़ाइल (सीएसवी, एक्सएमएल इत्यादि) को संसाधित करने के लिए एडेप्टर का एक सेट है। हम मुठभेड़ की उम्मीद करेंगे। विकास के शुरुआती हिस्से के दौरान हम डेटा एडाप्टर को संदर्भ के माध्यम से और कमांड का उपयोग करके हार्ड कोडिंग कर रहे थे। जाहिर है जब यह लाइव हो जाता है तो हम उस स्थिति को चाहते हैं जहां हम सिर्फ एक नया एडाप्टर लिख सकें और डीएलएल को फ़ोल्डर में फेंक दें और कोड को दोबारा बिना प्रक्रिया के चलाएं।कोड में अधिक डीएलएल लोड हो रहा है क्रैश
इसे लागू करने के लिए मैंने this question से कोड अनुकूलित किया। सवाल में कोड निर्माता में
string dllLocation = @"C:MyLocation\dllLocation";
DirectoryInfo dir = new DirectoryInfo(dllLocation);
var tempfiles = dir.GetFiles("*Adapter*.dll", SearchOption.AllDirectories); // This will need to be changed when we go live
foreach (var file in tempfiles)
{
Assembly tempAssembly = null;
//Before loading the assembly, check all current loaded assemblies in case already loaded
//has already been loaded as a reference to another assembly
//Loading the assembly twice can cause major issues
foreach (Assembly loadedAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
//Check the assembly is not dynamically generated as we are not interested in these
if (loadedAssembly.ManifestModule.GetType().Namespace != "System.Reflection.Emit")
{
//Get the loaded assembly filename
string loadedFilename = loadedAssembly.CodeBase.Substring(loadedAssembly.CodeBase.LastIndexOf('/') + 1);
//If the filenames match, set the assembly to the one that is already loaded
if (loadedFilename.ToUpper() == file.Name.ToUpper())
{
tempAssembly = loadedAssembly;
break;
}
}
}
//If the assembly is not aleady loaded, load it manually
if (tempAssembly == null)
{
tempAssembly = Assembly.LoadFrom(file.FullName);
}
Assembly a = tempAssembly;
बाद में इस प्रकार जब विधि चलाता है हम इस
private IEnumerable<IUniversalDataAdapter> DataAdapters
{
get
{
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in asm.GetTypes().Where(x => x.GetInterfaces().Contains(typeof(IUniversalDataAdapter))))
{
if (type.IsAbstract) continue; // can't create abstract classes
if (!dataAdapters.Any(y => y.GetType().Equals(type)))
{
IUniversalDataAdapter adapter = (IUniversalDataAdapter)Activator.CreateInstance(type);
dataAdapters.Add(adapter);
}
}
}
return dataAdapters;
}
}
जो सफलतापूर्वक डेटा एडेप्टर लोड करता है और उन्हें के रूप में मैं उम्मीद करेंगे इस्तेमाल की अनुमति देता है स्थित है।
प्रश्न के लिए अब, कोड के पहले बिट में हम अगर मैं
var tempfiles = dir.GetFiles("*.dll", SearchOption.AllDirectories);
दिनचर्या दुर्घटनाओं के लिए इसे बदल कोड की दूसरी बिट इस पर चलाता है से पहले लाइन
var tempfiles = dir.GetFiles("*Adapter*.dll", SearchOption.AllDirectories);
है दिनचर्या
private IEnumerable<IDataValidator> DataValidators
{
get
{
if (validators.Count == 0)
{
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in asm.GetTypes().Where(x => x.GetInterfaces().Contains(typeof(IDataValidator))))
{
if (!type.IsAbstract)
{
var validator = (IDataValidator)Activator.CreateInstance(type, context);
validators.Add(validator);
}
}
}
}
return validators;
}
}
संपादित करें: अपवाद जोड़ा
System.Reflection.ReflectionTypeLoadException was unhandled
HResult=-2146232830
Message=Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Source=mscorlib
StackTrace:
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.RuntimeModule.GetTypes()
at System.Reflection.Assembly.GetTypes()
at TTi.Data.Pipeline.Server.Common.DataPipeline.get_DataValidators() in C:\Users\anorcross\Source\Workspaces\Universal System\Data\Main\TTi.Data\TTi.Data.Pipeline.Server.Common\DataPipeline.cs:line 124
at TTi.Data.Pipeline.Server.Common.DataPipeline.CheckConfiguration(DataConfiguration config) in C:\Users\anorcross\Source\Workspaces\Universal System\Data\Main\TTi.Data\TTi.Data.Pipeline.Server.Common\DataPipeline.cs:line 528
at TTi.Data.Pipeline.Server.Common.DataPipeline.ProcessDataSource(IDataSource dataSource, DataConfiguration config) in C:\Users\anorcross\Source\Workspaces\Universal System\Data\Main\TTi.Data\TTi.Data.Pipeline.Server.Common\DataPipeline.cs:line 213
at TTi.Data.Test.Program.ImportTest(String testFolders) in C:\Users\anorcross\Source\Workspaces\Universal System\Data\Main\TTi.Data\TTi.Data.Test\Program.cs:line 362
at TTi.Data.Test.Program.Main(String[] args) in C:\Users\anorcross\Source\Workspaces\Universal System\Data\Main\TTi.Data\TTi.Data.Test\Program.cs:line 48
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
EndEdit:
DataValidators
निश्चित रूप से DataAdapters
दिनचर्या से पहले चलाता है। डेटा वैलिडेटर्स मुख्य कोड बेस में निहित कोड के बिट्स हैं और यह सुनिश्चित करने के लिए जांचें कि आयातित डेटा अपेक्षित प्रारूप का है। इस बिंदु पर हम उन्हें केवल लोड कर रहे हैं ताकि हम सुनिश्चित कर सकें कि आवश्यक लोग मौजूद हैं।
लोड किए गए असेंबली को देखते हुए, कोड के दोनों संस्करण एडाप्टर को आवश्यकतानुसार लोड करते हैं, लेकिन दूसरा संस्करण पहले की तुलना में अधिक लोड करता है जैसा कि मैं अपेक्षा करता हूं।
तो, tempfiles
का दूसरा संस्करण कोड के पूरी तरह से असंबंधित हिस्से की तरह दिखता है? और यदि हम पर्याप्त डेटा एडेप्टर जोड़ते हैं तो क्या यह कोड क्रैश हो जाएगा?
अपवाद और स्टैक ट्रेस क्या है? – rene
कुछ प्रश्न: क्या सभी फ़ाइलें .dll वास्तव में .NET dlls के साथ समाप्त हो रही हैं? यदि आप अप्रबंधित डीएलएस लोड करने का प्रयास करते हैं तो यह क्रैश हो जाएगा। क्या कोई डीएलएस है जो आपके डीएलएस द्वारा उसी स्थान पर संदर्भित किया जाता है? या कहीं जहां सिस्टम उन्हें ढूंढ सकता है (यानी बिन फ़ोल्डर या% windir% \ system32 आदि)? क्या आप 64 बिट प्रक्रिया के रूप में चल रहे हैं और क्या आप किसी भी असेंबली को 32 बिट अनमांडेड डीएलएल संदर्भित करने का प्रयास करते हैं (यह भी क्रैश होगा)? – mortb
@mortb हाँ, जहां तक मैं देख सकता हूं कि वे हमारे कोड या Nuget संकुल के सभी बिट्स हैं। कार्यक्रम 32 या 64 बिट के रूप में विशिष्ट है और नेट 4.6 चला रहा है। मैं विशेष रूप से समाधान फ़ोल्डर में देख रहा हूँ। – Andrew