我有以下代码:
namespace ConsoleApplication
{
static void Main(string[] args)
{
Device device = new Device();
device.Command += new EventHandler<DeviceSpecialArgs>(device_Command);
}
public static void device_Command(Object source, DeviceSpecialArgs args)
{
Console.WriteLine("Command: {0}, Reguest: {1}", args.Command, args.Request);
}
}
}
我必须做同样的事情,但是包含类型Device和DeviceSpecialArgs的程序集需要在运行时加载。我知道如何使用反射加载程序集但我发现事件处理部分令人费解:
namespace ConsoleApplication
{
static void Main(string[] args)
{
// Load the assembly
string dllPath = @"C:\Temp\Device.dll"
Assembly asm = Assembly.LoadFrom(dllPath);
// Instanciate Device
Type deviceType = asm.GetType("Device");
object device = Activator.CreateInstance(deviceType);
// How do I subscribe to the Command event?
}
// args would normally be a DeviceSpecialArgs but since that type is
// unknown at compile time, how do I prototype the handler?
public static void device_Command(Object source, ??? args)
{
Console.WriteLine("Command: {0}, Reguest: {1}", args.Command, args.Request);
}
}
如何使用反射订阅活动?另外,我应该如何对处理程序本身进行原型化,因为&#34; args&#34;在编译时是未知的?仅供参考,我是C#3和.NET 3.5。
答案 0 :(得分:1)
首先,看看MAF。
替代方法是向第一个程序集添加对第二个程序集的引用。然后在第二个程序集中创建几个接口,并在第一个程序集中创建类来实现它们:
public interface IDeviceSpecialArgs
{
string Command { get; }
string Request { get; }
}
public interface IDevice
{
event EventHandler<IDeviceSpecialArgs> Command;
}
第一次集会:
public sealed class DeviceSpecialArgs : EventArgs, IDeviceSpecialArgs
{
private readonly string command;
private readonly string request;
public string Command
{
get { return command; }
}
public string Request
{
get { return request; }
}
public DeviceSpecialArgs(string command, string request)
{
this.command = command;
this.request = request;
}
}
public class Device : IDevice
{
public event EventHandler<IDeviceSpecialArgs> Command;
...
}
在第二个程序集中,只需将新实例化的对象转换为相应的接口:
IDevice device = Activator.CreateInstance(deviceType) as IDevice;
现在您可以订阅Command
事件,因为它在IDevice
界面中声明:
device.Command += new EventHandler<IDeviceSpecialArgs>(device_Command);
编辑:如果您无法控制正在加载的程序集,请尝试以下代码。它只是使用第二个参数的EventArgs
类型创建一个处理程序,并使用反射来获取其属性:
internal class DeviceEvent
{
private readonly Type deviceType;
private readonly Type deviceSpecialArgsType;
public DeviceEvent()
{
// Load the assembly
const string dllPath = @"C:\Temp\Device.dll";
Assembly asm = Assembly.LoadFrom(dllPath);
// Get types
deviceType = asm.GetType("Device");
deviceSpecialArgsType = asm.GetType("DeviceSpecialArgs");
// Instantiate Device
object device = Activator.CreateInstance(deviceType);
// Subscribe to the Command event
deviceType.GetEvent("Command").AddEventHandler(device, (Delegate.CreateDelegate(typeof(EventHandler), GetType().GetMethod("Device_Command", BindingFlags.NonPublic))));
}
private void Device_Command(object sender, EventArgs e)
{
string command = deviceSpecialArgsType.GetProperty("Command", BindingFlags.Public).GetValue(e, null).ToString();
string request = deviceSpecialArgsType.GetProperty("Request", BindingFlags.Public).GetValue(e, null).ToString();
...
}
}