请查看下面的代码,该代码基于您拥有控制器类Controller的假设。它是一个带有约束CGeneric的泛型类,其中T:IRecord,两个具体记录类CRecordCustomer:IRecord和CRecordVipCustomer:Irecord。问题是如何在不知道运行时之前的t类型的情况下将事件处理程序附加到泛型类型?
public class CGeneric<T> where T:IRecord, new()
{
public delegate void OnCompleted();
public event OnCompleted completed;
private void ProcessStuff(T ConcreteRecordType)
{
T concreteInstance = default(T);
(concreteInstance as T).DoSomeInterfaceStuff();
if(this.completed !=null)
{
this.completed;
}
}
}
// This is how the controller class instantiates CGeneric<T>
// Using reflection gets all types that implement IRecord
// Then using one of those types (which is unknown at compile time):
class Controller
{
Type[] allTypes = Assembly.GetExecutingAssembly().GetTypes();
Type concreteType allTypes.Where(t => t.GetInterfaces().Contains(typeof(IRecord)) && !IgnoreType(t)).ToList()[0];
Type genericType = typeof(CGeneric<>);
genericType = genericType .MakeGenericType(
ConstructorInfo constructor = genericType .GetConstructor(new Type[] { });
Object genericInstance = constructor.Invoke(new Object[] { });
//This is where I need to hook to OnCompletedEvent
MethodInfo processmoethod = genericType .GetMethod("Process");
processmoethod.Invoke(genericInstance , concreteType );
}
答案 0 :(得分:2)
通常,您应该能够添加事件处理程序,如下所示:
OnCompleted handler = () => { /*event handler*/ };
genericType.GetEvent("completed").AddEventHandler(genericInstance, handler);
但是,您应该将OnCompleted
委托定义移到课堂外,以便能够在不知道T
的{{1}}的情况下引用它。
(注意:您的示例代码有很多其他错误会阻止您编译它)
答案 1 :(得分:0)
如果我理解你的错误,这可以帮助你http://www.codeproject.com/Articles/121923/Using-Reflection-to-Manage-Event-Handlers
答案 2 :(得分:0)
解决方案可能是这样的:
public delegate void OnCompleted();
public interface IRecord
{
void DoSomeInterfaceStuff();
event OnCompleted completed;
}
public interface IEvents
{
event OnCompleted completed;
}
public class CGeneric<T> : IEvents
where T:IRecord, new()
{
public event OnCompleted completed;
private void ProcessStuff(T ConcreteRecordType)
{
T concreteInstance = default(T);
concreteInstance.DoSomeInterfaceStuff();
if(this.completed !=null)
{
this.completed();
}
}
}
public class Record : IRecord
{
public void DoSomeInterfaceStuff()
{
}
}
可以用这种方式实例化:
Type toInstantiate = Type.GetType("CGeneric`1");
Type[] parameters = new Type[] { typeof(Record) };
Type instantiated = toInstantiate.MakeGenericType(parameters);
IEvents result = Activator.CreateInstance(instantiated) as IEvents;
result.completed += result_completed;
并且它不依赖于泛型类型。
答案 3 :(得分:0)
Lats说你有 eventName , handlerMethodName , objectOnWhichTheEventIsDefined , objectOnWhichTheEventHandlerIsDefined 。 eventName 和 handlerMethodName 是字符串,其余对象是对象数据类型。然后,您可以使用反射处理事件与处理程序,如下所示。
Object.create
完整的控制台示例如下所示。
public bool SubscribeEvent(string eventName, string handlerMethodName,
object objectOnWhichTheEventIsDefined,
object objectOnWhichTheEventHandlerIsDefined)
{
try
{
var eventInfo = objectOnWhichTheEventIsDefined.GetType().GetEvent(eventName);
var methodInfo = objectOnWhichTheEventHandlerIsDefined.GetType().
GetMethod(handlerMethodName);
// Create new delegate mapping event to handler
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, objectOnWhichTheEventHandlerIsDefined, methodInfo);
eventInfo.AddEventHandler(objectOnWhichTheEventIsDefined, handler);
return true;
}
catch (Exception ex)
{
// Log failure!
var message = "Exception while subscribing to handler. Event:" + eventName + " - Handler: " + handlerMethodName + "- Exception: " + ex;
Debug.Print(message);
return false;
}
}