需要帮助来动态创建静态泛型委托! 我需要使用Execute方法来订阅事件,在该事件中必须有对原始订阅方法“ subscriber”的调用。 代码:
/// <summary> Event subscriber </summary>
public static class EventSubscriber
{
public static bool SubscribeEvent<T>(this object source, string eventName, EventHandler<T> subscriber, int executeMaxCount = 1)
{
var eventInfo = source.GetType().GetEvents().FirstOrDefault(p => string.Compare(p.Name, eventName, StringComparison.InvariantCultureIgnoreCase) == 0);
if (eventInfo == null)
return false;
var method = eventInfo.EventHandlerType.GetMethod("Invoke");
if (method == null)
return false;
var prameters = method.GetParameters();
if (prameters.Length != 2 && prameters[1].GetType() != typeof(T))
return false;
eventInfo.AddEventHandler(source,
/* Dynamically create generic delegate like
(sender, e) => Execute(eventName, sender, e )
*/
);
return true;
}
private static void Execute<T>(string eventName, object sender, T e )
{
}
}
非常感谢!
答案 0 :(得分:0)
/// <summary> Dynamically create delegate </summary>
/// <param name="className">Event handler class name</param>
/// <param name="eventName">Event name</param>
/// <returns>Delegate</returns>
private static Delegate CreateDelegate(Type className, string eventName)
{
try
{
var codeProvider = new CSharpCodeProvider();
var compilerParameters = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true,
};
var assemblies = className.Assembly.GetReferencedAssemblies().ToList();
assemblies= assemblies.Union(typeof(EventSubscriber).Assembly.GetReferencedAssemblies()).ToList();
var assemblyLocations = assemblies.Select(a => Assembly.ReflectionOnlyLoad(a.FullName).Location).ToList();
// Type where event handler
assemblyLocations.Add(className.Assembly.Location);
// Type where I'm
assemblyLocations.Add(typeof(EventSubscriber).Assembly.Location);
compilerParameters.ReferencedAssemblies.AddRange(assemblyLocations.ToArray());
// Dynamic part generated from User text(code)
var executable = string.Format(@"namespace {0} {{ public static class PrivateExecutor{{ public static {1} Create() {{"
+ "{1} _result = (sender, args) => Subscriber.Execute(\"{2}\", sender, args);return _result;}}}}}}",
typeof(EventSubscriber).Namespace,
className.FullName,
eventName);
// Try to compile
var compilerResults = codeProvider.CompileAssemblyFromSource(compilerParameters, executable);
// Check compiler errors
if(compilerResults.Errors.OfType<CompilerError>().Count(e => !e.IsWarning) > 0)
{
var errors = new StringBuilder(string.Empty);
foreach(var err in compilerResults.Errors.OfType<CompilerError>())
errors.AppendFormat("{0} ", err.ErrorText);
throw new ArgumentException(string.Format("Handler : [{0}]. Event : [{1}]. Error : [{2}]", className, eventName, errors).Trim());
}
// Get executable method
var methinfo = compilerResults.CompiledAssembly.GetType(string.Format("{0}.PrivateExecutor", typeof(EventSubscriber).Namespace)).GetMethod("Create");
return (Delegate)methinfo.Invoke(null, null);
}
catch(Exception ex)
{
throw new ArgumentException(string.Format("{0}{1}", ex.Message, ex.InnerException).Trim());
}
}