如何将类转换为变量以调用函数并获取属性? 我被告知要查看反射,但我不知道在编译时不知道DLL时它是如何完成的。
要清楚:我有一个'main'类加载DLL,我想在DLL中创建一个类的实例并直接获取属性。
答案 0 :(得分:4)
你应该这样做:
Assembly asm = Assembly.Load("DLL File Path"); //load DLL from file
Type t = asm.GetType("Test.ExternalDllTest"); //fully qualified name
dynamic oDynamic = Activator.CreateInstance(t, args);//create an instance of specified type, and assign it to DYNAMIC object
编辑
oDynamic.SomeMethod(); //call the method of your type. Being DYNAMIC it will route the call to correct method.
当然,DLL
必须是托管DLL (所以用.NET
语言编写)
老实说,我没有编译这个,但基本上这是一个如何做到这一点的想法。
此处还有一个example,可能有所帮助。
答案 1 :(得分:2)
如果您正在讨论另一个.NET DLL,您可以使用它来加载程序集并获取所有类型:
var asm = Assembly.LoadFile("yourassembly.dll");
foreach (var t in asm.GetTypes())
{
Console.WriteLine("Type: {0}", t.Name);
}
您可以使用Activator
:
Activator.CreateInstance(t, additional arguments);
或者您可以使用GetConstructors
获取该类型的所有公共构造函数的列表:
var constructors = t.GetConstructors();
但是,除非你知道你正在寻找什么类型以及它的构造函数参数是什么,尝试实例化并使用它是没有意义的。
答案 2 :(得分:0)
编写一个可通过Loaded DLL和Loading程序访问的界面(IKnowAboutSomething)。
扫描已加载的DLL并找到实现此接口的类。
然后你可以使用Activator.CreateInstance创建你找到的类型的实例(你知道界面的地方)
现在,您只需在IKnowAboutSomething.GetThingINeed()等上调用方法,就可以在编译时与您不了解的内容进行交互。 (嗯,你知道一点,因为他们正在使用接口,因此有一个协议)
将此代码放在两个项目均可访问的外部DLL(例如Core.Dll)中。
using System.IO;
public interface ISettings
{
/// <summary>
/// Will be called after you Setup has executed if it returns True for a save to be performed. You are given a Stream to write your data to.
/// </summary>
/// <param name="s"></param>
/// <remarks></remarks>
void Save(Stream s);
/// <summary>
/// Will be called before your Setup Method is to enable the loading of existing settings. If there is no previous configuration this method will NOT be called
/// </summary>
/// <param name="s"></param>
/// <remarks></remarks>
void Load(Stream s);
/// <summary>
/// Your plugin must setup a GUID that is unique for your project. The Main Program will check this and if it is duplicated your DLL will not load
/// </summary>
/// <value></value>
/// <returns></returns>
/// <remarks></remarks>
Guid Identifier { get; }
/// <summary>
/// This Description will be displayed for the user to select your Plugin. You should make this descriptive so the correct one is selected in the event they have multiple plugins active.
/// </summary>
/// <value></value>
/// <returns></returns>
/// <remarks></remarks>
string Description { get; }
}
现在在您的主项目中添加对上述DLL的引用。
在您的主项目中扫描您计划加载的DLL的目录(c:\ myDlls * .dll)使用DirectoryInfo(或类似)进行扫描。
找到DLL后,使用程序集asm = Assembly.LoadFrom(filename)来加载它。
现在您可以在主项目中执行此操作。
foreach (Type t in asm.GetTypes())
{
if (typeof(ISettings).IsAssignableFrom(t))
{
//Found a Class that is usable
ISettings loadedSetting = Activator.CreateInstance(t);
Console.WriteLine(loadedSetting.Description);
}
}
答案 3 :(得分:0)
实施例。这是我用来搜索插件目录树并返回WPF ValueConverter类列表的方法...
private static List<IValueConverter> GetValueConverters( string rootDirectoryName)
{
List<IValueConverter> result = new List<IValueConverter>();
string[] exts = new string[]{"*.exe", "*.dll"};
DirectoryInfo di = new DirectoryInfo(rootDirectoryName);
foreach(string ext in exts)
{
foreach(FileInfo fi in (di.GetFiles(ext, SearchOption.AllDirectories)))
{
Assembly a = Assembly.LoadFrom(fi.FullName);
try
{
List<Type> ts = a.GetExportedTypes().ToList();
foreach (Type t in ts)
{
var d2 = t.GetInterfaces().Where(q => q.Name == "IValueConverter");
if (d2.Count() > 0)
{
result.Add(Activator.CreateInstance(t) as IValueConverter);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
return result;
}
代码在目录树中搜索匹配&#39; dll&#39;和&#39; exe&#39;。当它找到一个时,它会尝试加载它,然后查看其中是否有任何WPF ValueConverters。
如果找到一个,代码会创建一个实例并将其添加到列表中,并最终返回列表。当然,&#39; dll&#39; s&#39;和&#39; exe&#39;必须在管理的世界。如果您对ValueConverters以外的类感兴趣,则必须相应地更改它。
这是一种专门构建的方法(即,我知道结果会发生什么),这里的代码仅作为示例给出......