我需要通過僅反射才能使用位於新域內指定文件中的.dll庫。一切都很好,我可以獲取信息,方法,類型,但是當我真的想要Invoke
方法之一時,異常會引發System.Reflection.TargetException
(對象與目標對象不匹配)。毛刺是,當我設置「路徑」只有名稱爲「Filter.dll」的名稱,並在Debug目錄中有庫時,應用程序工作。當我移動庫並將其路徑更改爲@「D:/Dropbox/SchoolProject/MyPlugins/Filter.dll」時,會引發異常。如何通過ReflectionOnly正確獲取Type的方法用法
我的代碼:
AppDomain domain = AppDomain.CreateDomain("MyNewDomain"); //new domain for assembly
//parameters are @"D:/Dropbox/SchoolProject/MyPlugins/Filter.dll", "Plugins.Filter"
ObjectHandle objh = domain.CreateInstanceFrom(_selectedLibraryDirectives.Item1 + _selectedLibraryDirectives.Item2 + ".dll", _selectedLibraryDirectives.Item3);
object obj = objh.Unwrap();
if (RemotingServices.IsTransparentProxy(obj))
{
Type domainType = null;
foreach (var ass in AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies())
{
//domainType's name and fullname is "Filter", "Plugins.Filter"
//so I would think this is type I want, but exception about wrong
//type is raised when using domainType for method.Invoke
domainType = ass.DefinedTypes.First().AsType();
}
//type's name and fullname is "Filter", "Plugins.Filter",
//when Filter.dll is in Debug dir, even if name of the file in
//domain.CreateInstanceFrom is set to path to MyPlugins, invoking method works
//and "MarshalByRefObject", "System.MarshalByRefObject" in case library
// isn't in Debug directory, invoking method crashes on wrong type
Type type = obj.GetType();
//get method by method name previously added as ListBox Item
MethodInfo method = domainType.GetMethod(PluginMethodsListBox.SelectedItem.ToString());
//exception is usually raised with invoking
Tuple<string, string> tuple = (Tuple<string, string>)method.Invoke(domainType, new object[] { "hello" });
PluginsPluginNameValueLabel.Text = method.Name;
PluginsPluginDescValueLabel.Text = tuple.Item2;
}
這是我第一次處理庫,反射僅這樣。我很困惑,爲什麼我可以在一個文件夾中使用庫,但不在其他文件夾中,即使條件相同。當我可以從默認文件夾以外的庫中獲取MethodInfo時,爲什麼我無法正確獲取它的類型。
的代碼,其餘用於獲取有關圖書館方法的信息,並保存到UI元素,當庫是由用戶選擇:
foreach (var library in _libraries)
{
if (PluginsListBox.SelectedItem + ".dll" == library.Name)
{
//getting library info
Assembly ass = Assembly.ReflectionOnlyLoadFrom(library.DirectoryName + @"\" + library.Name);
var types = ass.GetTypes();
Type type = null;
foreach (var t in types)
{
if (t.Name + ".dll" == library.Name)
{
_selectedLibraryDirectives = new Tuple<string, string, string>(library.DirectoryName [email protected]"\", t.Name, t.FullName);
type = t;
}
}
//viewing list of methods in ListBox
if (type != null)
{
PluginMethodsListBox.Items.Clear();
foreach (MethodInfo method in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance))
{
if (method.ReturnType == typeof(Tuple<string,string>) && method.GetParameters().Length == 1 && method.GetParameters()[0].ParameterType.FullName == "System.String")
{
var a = method.GetParameters();
PluginMethodsListBox.Items.Add(method.Name);
}
}
}
}
}
感謝爲解決或瞭解這一情況的任何意見問候。
編輯(庫代碼):
[Serializable]
public class Filter : MarshalByRefObject
{
public void noParamConsTest() { Console.WriteLine("noparamconsoletest");}
public void paramConstTest(string s) { Console.WriteLine(s); }
public Tuple<string,string> FilterCommas(string text)
{
//..
return new Tuple<string, string>(returnString, string.Empty);
}
解決方案:
我沒有爲propper,乾淨優雅的解決方案足夠多的時間,所以我改變做法了一下。我通過插件目錄設置文件觀察器,當發生更改時,我只是將庫複製到CurrentDomain工作目錄。從那裏裝載組件根本沒有問題。
但我的問題沒有得到答覆。爲什麼AppDomain,即使他們已經將基路徑,相對路徑等設置爲自定義路徑,在缺省工作目錄中查找庫,而不是指定庫或其中的庫。只從自定義目錄加載庫到新的域似乎是不可能的。
如果有人知道解釋,請讓我知道。謝謝
很好的組裝var名稱(+1) – silver