如何通过ReflectionOnly正确获取Type的方法用法
我需要通过仅反射才能使用位于新域内指定文件中的.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,即使他们已经将基路径,相对路径等设置为自定义路径,在缺省工作目录中查找库,而不是指定库或其中的库。只从自定义目录加载库到新的域似乎是不可能的。
如果有人知道解释,请让我知道。谢谢
你应该调用的实例obj
的方法,而不是类型domainType
:
Tuple<string, string> tuple = (Tuple<string, string>)method.Invoke(obj, new object[] { "hello" });
关于反思,只有:
不要在反射只读模式加载程序集,如果你想要调用它的代码。
加载组件进入只反射上下文,在那里它可以是 检验,但不会执行。
使用常规的Assembly.Load
方法之一。
即使我尝试这种方法,问题perzists。我需要为加载的程序集创建新的域,所以我有这个代码 'AppDomain domain = AppDomain.CreateDomain(“NewDomainName”,new Evidence(),new AppDomainSetup(){ApplicationName =“FriendlyName”,ApplicationBase = _selectedLibraryDirectives.Item1} ); domain.Load(“Filter”);' 但仍然,我将ApplicationBase设置到我的目录,当我有默认目录Filter.dll时,程序集加载,当我将Filter.dll移动到我的目录时,FileNotFoundException被引发与过滤器全名 – Qerts
的消息它看起来像我无法更改此新域的探测目录,但它已基地设置为我的目录路径 – Qerts
@Qerts,尝试使用LoadFrom提供组装路径 – Guillaume
很好的组装var名称(+1) – silver