我正在创建一个 Windows Mobile 应用程序,并且在使用EventPublication的.
我的订阅位于容器的主目录上,而发布位于从 OpenNETCF.IoC.UI.SmartPart 继承的对象上
应用程序启动
Public Class Startup
Inherits SmartClientApplication(Of MainContainer)
Public Shared Sub Main()
Dim appStarter As New Startup
appStarter.Start()
End Sub
End Class
订阅 MainContiner 表单
<EventSubscription(EventNames.Navigate, ThreadOption.UserInterface)> _
Public Sub NavigateSmartPart(ByVal sender As Object, ByVal e As GenericEventArgs(Of String))
.....
End Sub
出版商
Namespace Views
Public Class ViewLogon
<EventPublication(EventNames.Navigate)> _
Friend Event NavigateToSmartPart As EventHandler(Of GenericEventArgs(Of String))
Public Overrides Sub OnActivated()
End Sub
End Class
End Namespace
问题
如果我尝试编写这个聪明的部分,我在OpenNETCF.IoC.ObjectFactory.AddCollectionEventHandlers<TKey, TItem>
方法中得到 NullReferenceException 就 source.EventInfo.AddEventHandler(instance, intermediate);
行了。
删除EventPublication
作品没有任何问题。
private static void AddCollectionEventHandlers<TKey, TItem>(object instance, IEnumerable<KeyValuePair<TKey, TItem>> collection, PublicationDescriptor[] sourceEvents, SubscriptionDescriptor[] eventSinks)
{
if (collection == null) return;
var invokerControl = RootWorkItem.Items.Get<TheInvoker>("IOCEventInvoker");
foreach (var item in collection)
{
if (instance.Equals(item.Value)) continue;
if((item.Value is WorkItem) && (collection is ServiceCollection))
{
// this prevents recursion (and a stack overflow) for WorkItems
continue;
}
foreach (var source in sourceEvents)
{
// wire up events
foreach (var sink in GetEventSinksFromTypeByName(item.Value.GetType(), source.Publication.EventName, ThreadOption.Caller))
{
Delegate d = Delegate.CreateDelegate(source.EventInfo.EventHandlerType, item.Value, sink);
source.EventInfo.AddEventHandler(instance, d);
}
foreach (var sink in GetEventSinksFromTypeByName(item.Value.GetType(), source.Publication.EventName, ThreadOption.UserInterface))
{
// wire up event handlers on the UI thread
Delegate d = Delegate.CreateDelegate(source.EventInfo.EventHandlerType, item.Value, sink);
if (source.EventInfo.EventHandlerType == typeof(EventHandler))
{
// unsure why so far but this fails if the EventHandler signature takes a subclass of EventArgs as the second param
// and if you use just EventArgs, the arg data gets lost
BasicInvoker invoker = new BasicInvoker(invokerControl, d);
Delegate intermediate = Delegate.CreateDelegate(source.EventInfo.EventHandlerType, invoker, invoker.HandlerMethod);
source.EventInfo.AddEventHandler(instance, intermediate);
}
else if ((source.EventInfo.EventHandlerType.IsGenericType) && (source.EventInfo.EventHandlerType.GetGenericTypeDefinition().Name == "EventHandler`1"))
{
BasicInvoker invoker = new BasicInvoker(invokerControl, d);
Delegate intermediate = Delegate.CreateDelegate(source.EventInfo.EventHandlerType, invoker, invoker.HandlerMethod);
source.EventInfo.AddEventHandler(instance, intermediate);
}
}
}
// back-wire any sinks
foreach (var sink in eventSinks)
{
foreach (var ei in GetEventSourcesFromTypeByName(item.Value.GetType(), sink.Subscription.EventName))
{
try
{
// (type, consumer instance, consumer method)
Delegate d = Delegate.CreateDelegate(ei.EventHandlerType, instance, sink.MethodInfo);
if (sink.Subscription.ThreadOption == ThreadOption.Caller)
{
ei.AddEventHandler(item.Value, d);
}
else
{
// wire up event handlers on the UI thread
if ((ei.EventHandlerType.IsGenericType) && (ei.EventHandlerType.GetGenericTypeDefinition().Name == "EventHandler`1")
|| (ei.EventHandlerType == typeof(EventHandler))
#if !WINDOWS_PHONE
|| (ei.EventHandlerType == typeof(KeyEventHandler))
#endif
)
{
// unsure why so far but this fails if the EventHandler signature takes a subclass of EventArgs as the second param
// and if you use just EventArgs, the arg data gets lost
BasicInvoker invoker = new BasicInvoker(invokerControl, d);
Delegate intermediate = Delegate.CreateDelegate(ei.EventHandlerType, invoker, invoker.HandlerMethod);
ei.AddEventHandler(item.Value, intermediate);
}
else
{
throw new ArgumentException("ThreadOption.UserInterface only supported for EventHandler and EventHandler<T> events");
}
}
}
catch (ArgumentException)
{
throw new ArgumentException(string.Format("Unable to attach EventHandler '{0}' to '{1}'.\r\nDo the publisher and subscriber signatures match?", ei.Name, instance.GetType().Name));
}
}
}
WorkItem wi = item.Value as WorkItem;
if (wi != null)
{
AddEventHandlers(instance, wi, false);
}
}
}
堆栈跟踪
at System.Reflection.EventInfo.AddEventHandler(Object target, Delegate handler)
at OpenNETCF.IoC.ObjectFactory.AddCollectionEventHandlers[TKey,TItem](Object instance, IEnumerable`1 collection, PublicationDescriptor[] sourceEvents, SubscriptionDescriptor[] eventSinks)
at OpenNETCF.IoC.ObjectFactory.AddEventHandlers(Object instance, WorkItem root, Boolean walkUpToRoot)
at OpenNETCF.IoC.ObjectFactory.AddEventHandlers(Object instance, WorkItem root)
at OpenNETCF.IoC.ObjectFactory.DoInjections(Object instance, WorkItem root)
at OpenNETCF.IoC.ManagedObjectCollection`1.Add(ISmartPart item, String id, Boolean expectNullId)
at OpenNETCF.IoC.ManagedObjectCollection`1.AddNew(Type typeToBuild, String id, Boolean expectNullId, Boolean wrapDisposables)
at OpenNETCF.IoC.ManagedObjectCollection`1.AddNew(Type typeToBuild, String id)
at OpenNETCF.IoC.ManagedObjectCollection`1.AddNew[TTypeToBuild](String id)
at StockMovement.IoC.Container.RegisterViews()
at StockMovement.IoC.Container.RegisterParts(DeckWorkspace workspace)
at StockMovement.MainContainer.MainContainerLoad(Object sender, EventArgs e)
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Form._SetVisibleNotify(Boolean fVis)
at System.Windows.Forms.Control.set_Visible(Boolean value)
at System.Windows.Forms.Application.Run(Form fm)
at OpenNETCF.IoC.UI.SmartClientApplication`1.OnApplicationRun(Form form)
at OpenNETCF.IoC.UI.SmartClientApplication`1.Start(IModuleInfoStore store)
at OpenNETCF.IoC.UI.SmartClientApplication`1.Start()
at StockMovement.Startup.Main()