// This class is deployed as an assembly consisting of one DLL,
// called HelloWorld.dll.
using System;
public class HelloWorld {
// Constant Hello World string.
private const String m_helloWorld = "Hello World";
// Default public constructor.
public HelloWorld() {
}
// Print "Hello World" plus the passed text.
public void PrintHello(String txt) {
// Output to the Console.
Console.WriteLine(m_helloWorld + " " + txt);
}
}// Illustrates reflection's late binding functionality.
// Calls the PrintHello method on a dynamically loaded
// and created instance of the HelloWorld class.
using System;
using System.Reflection;
public class CSharpLateHello {
public static void Main() {
// Load the assembly to use.
Assembly assem = Assembly.Load("HelloWorld");
// Get the type to use from the assembly.
Type helloType = assem.GetType("HelloWorld");
// Get the method to call from the type.
MethodInfo printMethod = helloType.GetMethod("PrintHello");
// Create an instance of the HelloWorld class.
Object obj = Activator.CreateInstance(helloType);
// Create the args array.
Object[] args = new Object[1];
// Set the arguments.
args[0] = "From CSharp Late Bound";
// Invoke the PrintHello method.
printMethod.Invoke(obj, args);
}
}
InvokeMember 和 CreateInstance
使用 Type.InvokeMember 可调用类型的成员。各个类(如 System.Activator 和 System.Reflection.Assembly)的 CreateInstance 方法是特殊形式的 InvokeMember,它们可新建特定类型的实例。Binder 类用于在这些方法中进行重载决策和参数强制。以下代码示例显示参数强制(类型强制)和成员选择三种可能的组合。在第 1 种情况中,不需要任何参数强制或成员选择。在第 2 种情况中,只需要成员选择。在第 3 种情况中,只需要参数强制。[C#]
public class CustomBinderDriver
{
public static void Main (string[] arguments)
{
Type t = typeof (CustomBinderDriver);
CustomBinder binder = new CustomBinder();
BindingFlags flags = BindingFlags.InvokeMethod|BindingFlags.Instance|
BindingFlags.Public|BindingFlags.Static; //Case 1. Neither argument coercion nor member selection is needed.
args = new Object[] {};
t.InvokeMember ("PrintBob", flags, binder, null, args); //Case 2. Only member selection is needed.
args = new Object[] {42};
t.InvokeMember ("PrintValue", flags, binder, null, args); //Case 3. Only argument coercion is needed.
args = new Object[] {"5.5"};
t.InvokeMember ("PrintNumber", flags, binder, null, args);
} public static void PrintBob ()
{
Console.WriteLine ("PrintBob");
} public static void PrintValue (long value)
{
Console.WriteLine ("PrintValue ({0})", value);
}
public static void PrintValue (String value)
{
Console.WriteLine ("PrintValue\"{0}\")", value);
}
public static void PrintNumber (double value)
{
Console.WriteLine ("PrintNumber ({0})", value);
}
}
// called HelloWorld.dll.
using System;
public class HelloWorld {
// Constant Hello World string.
private const String m_helloWorld = "Hello World";
// Default public constructor.
public HelloWorld() {
}
// Print "Hello World" plus the passed text.
public void PrintHello(String txt) {
// Output to the Console.
Console.WriteLine(m_helloWorld + " " + txt);
}
}// Illustrates reflection's late binding functionality.
// Calls the PrintHello method on a dynamically loaded
// and created instance of the HelloWorld class.
using System;
using System.Reflection;
public class CSharpLateHello {
public static void Main() {
// Load the assembly to use.
Assembly assem = Assembly.Load("HelloWorld");
// Get the type to use from the assembly.
Type helloType = assem.GetType("HelloWorld");
// Get the method to call from the type.
MethodInfo printMethod = helloType.GetMethod("PrintHello");
// Create an instance of the HelloWorld class.
Object obj = Activator.CreateInstance(helloType);
// Create the args array.
Object[] args = new Object[1];
// Set the arguments.
args[0] = "From CSharp Late Bound";
// Invoke the PrintHello method.
printMethod.Invoke(obj, args);
}
}
InvokeMember 和 CreateInstance
使用 Type.InvokeMember 可调用类型的成员。各个类(如 System.Activator 和 System.Reflection.Assembly)的 CreateInstance 方法是特殊形式的 InvokeMember,它们可新建特定类型的实例。Binder 类用于在这些方法中进行重载决策和参数强制。以下代码示例显示参数强制(类型强制)和成员选择三种可能的组合。在第 1 种情况中,不需要任何参数强制或成员选择。在第 2 种情况中,只需要成员选择。在第 3 种情况中,只需要参数强制。[C#]
public class CustomBinderDriver
{
public static void Main (string[] arguments)
{
Type t = typeof (CustomBinderDriver);
CustomBinder binder = new CustomBinder();
BindingFlags flags = BindingFlags.InvokeMethod|BindingFlags.Instance|
BindingFlags.Public|BindingFlags.Static; //Case 1. Neither argument coercion nor member selection is needed.
args = new Object[] {};
t.InvokeMember ("PrintBob", flags, binder, null, args); //Case 2. Only member selection is needed.
args = new Object[] {42};
t.InvokeMember ("PrintValue", flags, binder, null, args); //Case 3. Only argument coercion is needed.
args = new Object[] {"5.5"};
t.InvokeMember ("PrintNumber", flags, binder, null, args);
} public static void PrintBob ()
{
Console.WriteLine ("PrintBob");
} public static void PrintValue (long value)
{
Console.WriteLine ("PrintValue ({0})", value);
}
public static void PrintValue (String value)
{
Console.WriteLine ("PrintValue\"{0}\")", value);
}
public static void PrintNumber (double value)
{
Console.WriteLine ("PrintNumber ({0})", value);
}
}
授人以鱼不如授人以渔,谢谢了~~
object newObject = subAppAssembly.CreateInstance(type);
如:IMyProg.ITest接口在testbase.cs中,Test类实现ITest,位于test [DLL]项目test.cs中我们在第一个项目中包含接口定义即可,运行时得到所有dll的清单string[] dllNames,然后foreach(string s in dllNames),Assembly a=Assembly.LoadFrom(s);再foreach(Type t in a.GetTypes()),if(t.GetInterface("IMyProg.ITest")!=null) ITest iTest=(ITest) System.Activator.CreateInstance(t)
用此种方法,我们的项目得到了极大的灵活性,不过设计时花了一些时间
north_star(北极星) 你认为设计需要多少时间?其实很简单。
下面是一个简单的方案:
protected void Application_Start(Object sender, EventArgs e)
{
Assembly a1=typeof(EM.Msg).Assembly;
System.Text.StringBuilder sb=new System.Text.StringBuilder();
foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
foreach(AssemblyName an in asm.GetReferencedAssemblies())
{
if(an.FullName==a1.FullName)
{
foreach(Type t in asm.GetTypes())
{
if(t.IsSubclassOf(typeof(EM.Msg)))
{
ConstructorInfo ci=t.GetConstructor(new Type[0]);
if(ci!=null)
{
EM.Msg msg=ci.Invoke(new object[0]) as EM.Msg;
sb.Append(msg.GetMessage());
sb.Append("<br>");
}
}
}
break;
}
}
}
Application["msg"]=sb.ToString();
}
其中,,EM.Msg是EMMsg.dll里的一个abstract class
用asm.GetReferencedAssemblies()可以得到所有引用EMMsg.dll的Assembly
这个方法好处是它不需要循环mscorlib等大规模的类库,效率非常的高。如果想效率再高点,
可以这样:
EMMsg.dll 定义基本的interface或abstract class
Global.dll(包含GlobalApplication的那个) - - - - > EMMsg.dll
负责执行类似上面代码的过程。
Addin.dll(包含扩展的类,但是这个类已经没有必要引用EMMsg.dll了)
AddinAdapter.dll - - - - > EMMsg.dll那么在Global里,可以查到这两个Assembly引用了EMMsg.dll:Global,AddinAdapter然后调用AddinAdapter.Adapter.GetMessage()
。注释---- ( GetMessate -> Addin.TrueService.GetMessage() )这个方案虽然多了个AddinAdapter,
但是灵活在:Addin.TrueServivce已经不需要有什么继承和实现上的约束了。
因为它是被AddinAdapter所知道的。而且,这些Assembly都是很小的,所以循环Type的时候花的时间很少
所以你不需要自己去加载那些dll
我也在找.
我所说的花时间设计,指的是接口功能的取舍,因为要应付客户不断变化的需求,力争设计成功后,如果需要更改不会对程序框架造成大的冲击,并且容易维护
那是具体程序的接口的实现上了。而不是加载类型的实现上.
我使用的是统一的
public ITypeProvider
{
Type QueryType(Type t);
}
应用程序框架(OA-CRM-DESKTOP)
负责维护ITypeProvider的实现列表。
其他功能全部基于该框架开发。
框架所希望得到外部补充的协议并没有指定要求定义在某个Assembly里。
但有一个 TypeProvider.dll 里就定义了 ITypeProvider (也是该dll的唯一类型)
所有基于该框架的都可以实现ITypeProvider里提供自己的扩充。
也可以访问那列表来取得它想得到的类型。