I am using Prism 4 and MEF for a WPF project. I have some DLL that needs to be loaded from a directory. These DLL implements IModule through IGame and are properly formed (or at least I think so) :
[Module(ModuleName = "SnakeModule")]
class SnakeModule : IGame
{
public void Initialize()
{
Console.WriteLine("test");
}
public void StartGame()
{
throw new NotImplementedException();
}
}
Currently, the main project is compiling but the module doesn't get initialized. I have trouble understanding how to setup my bootstrapper and the documentation isn't helping much since it doesn't have full example with a DirectoryModuleCatalog. The modularity quickstart isn't compiling either. Here is my bootstrapper :
class BootStrap : MefBootstrapper
{
protected override DependencyObject CreateShell()
{
return ServiceLocator.Current.GetInstance<Shell>();
}
protected override void InitializeShell()
{
Application.Current.MainWindow = (Window)this.Shell;
Application.Current.MainWindow.Show();
}
protected override void ConfigureAggregateCatalog()
{
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(BootStrap).Assembly));
}
protected override IModuleCatalog CreateModuleCatalog()
{
DirectoryModuleCatalog catalog = new DirectoryModuleCatalog() { ModulePath = #"..\..\..\GameTestLib\bin\Debug" };
return catalog;
}
protected override void ConfigureContainer()
{
base.ConfigureContainer();
}
}
Paths for the DLLs are correct. To sum up, my question is : How should I setup my bootstrapper ?
First, and since you're using Prism, I suggest that you go with ModuleExport, as follows :
[ModuleExport("SnakeModule", typeof(IGame))]
But your problems actually comes from the fact you didn't set your class as a public one, therefore preventing the discovery of your module. So you need to change your code to this :
[ModuleExport("SnakeModule", typeof(IGame))]
public class SnakeModule : IGame
{
public void Initialize()
{
Console.WriteLine("test");
}
public void StartGame()
{
throw new NotImplementedException();
}
}
And it should be fine !
Related
I have to use a system file Watcher into a Windows service.
I write a wrap class and I put it into the service class as shown below :
public partial class CaptureRecordingsService : ServiceBase
{
FileSystemWatcherWrapper myFSWrapper;
public CaptureRecordingsService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
System.Diagnostics.Debugger.Launch();
myFSWrapper = new FileSystemWatcherWrapper();
}
protected override void OnStop()
{
}
}
}
The class works done in Windows form but in the service the methods are not called.
Can someone help me?
I'm doing CLR wrapper. It builds successfully. Problem is that when I reference wrapper .dll in c# project RegisterMessageCallback method is totally absent. Here is what I see in metadata:
public class ATFeedWrapper : IDisposable
{
public ATFeedWrapper();
public sealed override void Dispose();
public void Login();
protected virtual void Dispose(bool A_0);
}
And here is wrapper class .h:
public ref class ATFeedWrapper
{
public:
ATFeedWrapper();
void Login();
void RegisterMessageCallback(void(*clbck)(string));
~ATFeedWrapper();
private:
ATFeedClient* client;
};
and .cpp:
ATFeedWrapper::ATFeedWrapper()
{
client = new ATFeedClient();
}
void ATFeedWrapper::Login()
{
client->Login();
}
void ATFeedWrapper::RegisterMessageCallback(void(*clbck)(string))
{
client->RegisterMessageCallback(*clbck);
}
ATFeedWrapper::~ATFeedWrapper()
{
delete client;
}
What's going on? Why is it missing?
I can't get rid of this problem. It's very strage, when I try to run my NUnit test in Debug mode, I get the expected result but when I just run it normally, the result is Wrong.
What i'm trying to do is detect Binding errors. Here is a sample
[TestFixture, RequiresSTA]
public class BindingTests
{
[Test]
public void T1_BindingErrorsExpected()
{
string error = null;
using (var listener = new ObservableTraceListener())
{
listener.TraceCatched += s => error = s;
TextBlock myText = new TextBlock();
UserControl control = new UserControl();
Binding myBinding = new Binding("BadBinding");
myBinding.Source = control;
myText.SetBinding(TextBlock.BackgroundProperty, myBinding);
}
Assert.IsNotNull(error);
}
}
And the ObservableTraceListener
public sealed class ObservableTraceListener : DefaultTraceListener
{
private readonly StringBuilder _Builder = new StringBuilder();
public ObservableTraceListener()
{
PresentationTraceListener.Add(SourceLevels.Error, this);
}
public new void Dispose()
{
Flush();
Close();
PresentationTraceListener.Remove(this);
base.Dispose();
}
public override void Write(string message)
{
_Builder.Append(message);
}
public override void WriteLine(string message)
{
Write(message);
if (TraceCatched != null)
TraceCatched(_Builder.ToString());
_Builder.Clear();
}
public event Action<string> TraceCatched;
}
public static class PresentationTraceListener
{
public static void Add(SourceLevels level, TraceListener trace)
{
PresentationTraceSources.DataBindingSource.Listeners.Add(trace);
PresentationTraceSources.DataBindingSource.Switch.Level = level;
PresentationTraceSources.ResourceDictionarySource.Listeners.Add(trace);
PresentationTraceSources.ResourceDictionarySource.Switch.Level = level;
}
public static void Remove(TraceListener trace)
{
PresentationTraceSources.DataBindingSource.Listeners.Remove(trace);
PresentationTraceSources.ResourceDictionarySource.Listeners.Remove(trace);
}
}
Result in debug -> Fail (What I expect)
Result in Run-> Success (Not what expected)
Thanks MatthewMartin but I found the solution looking at https://github.com/bblanchon/WpfBindingErrors
The probem was my ObservableTraceListener.
I needed to add a static constructor calling PresentationTraceSources.Refresh() to get it works correctly. As said in MSDN doc, it Refreshes trace sources, by forcing the app.config file to be re-read. So, some initialization was just done when I started the test in "debug" mode, which probably caused the app.config file to be read.
MSDN doc -> PresentationTraceSources.Refresh() http://msdn.microsoft.com/en-us/library/system.diagnostics.presentationtracesources.refresh%28v=vs.100%29.aspx
Here is my final ObservableTraceListener and the PresentationTraceListener is the same as the one in the question
public sealed class ObservableTraceListener : TraceListener
{
private readonly StringBuilder _Builder = new StringBuilder();
static ObservableTraceListener()
{
PresentationTraceSources.Refresh();
}
public ObservableTraceListener()
{
PresentationTraceListener.Add(SourceLevels.Error, this);
}
public new void Dispose()
{
Flush();
Close();
PresentationTraceListener.Remove(this);
base.Dispose();
}
public override void Write(string message)
{
_Builder.Append(message);
}
public override void WriteLine(string message)
{
_Builder.Append(message);
if (TraceCatched != null)
TraceCatched(_Builder.ToString());
_Builder.Clear();
}
public event Action<string> TraceCatched;
}
Posting an answer because a comment would be too small to hold what I want to say...
There is no reference to PresentationTraceListener on the internet-- how it treats the TraceListener is important because AFAIK the PresentationTraceListener is what calls the Write/WriteLine methods of the TraceListener (possibly indirectly via TraceSource)
This code below compiles in a brand new project. If I Write(x), I get null, if I writeLine(x), I get a value. Generally when you write a custom TraceListener, you redirect all the overloads to a single method so that they all behave the same (Write and WriteLine should be identical except WriteLine tacks a newline onto the message for the caller.)
Another observation is that System.Diagnostics trace is a quirky logging library whose main advantage is that it is always available even when there is some barrier to using 3rd party libraries. System.Diagnostics trace really wants you to register a TraceSwitch, TraceListener in your app.config or web.config and use that to enable & disable trace. It also requires the the TRACE flag be registered (in the same way the DEBUG flag gets registered, in the project properities-- by default TRACE is defined for DEBUG and RELEASE)
[TestFixture, RequiresSTA]
public class BindingTests
{
[Test]
public void T1_BindingErrorsExpected()
{
string error = null;
using (var listener = new ObservableTraceListener())
{
listener.TraceCatched += s => error = s;
//TextBlock myText = new TextBlock();
//UserControl control = new UserControl();
//Binding myBinding = new Binding("BadBinding");
//myBinding.Source = control;
//myText.SetBinding(TextBlock.BackgroundProperty, myBinding);
PresentationTraceSources.DataBindingSource.TraceEvent(TraceEventType.Error,0, "Hello World!");
}
Assert.IsNotNull(error);
Console.WriteLine(error);
}
}
public sealed class ObservableTraceListener : TraceListener
{
private readonly StringBuilder _Builder = new StringBuilder();
public ObservableTraceListener()
{
//PresentationTraceListener.Add(SourceLevels.Error, this);
}
protected override void Dispose(bool disposing)
{
Flush();
Close();
//PresentationTraceListener.Remove(this);
}
public override void Write(string message)
{
_Builder.Append(message);
}
public override void WriteLine(string message)
{
Write(message);
if (TraceCatched != null)
TraceCatched(_Builder.ToString());
_Builder.Clear();
}
public event Action<string> TraceCatched;
}
I have this issue only in MonoTouch 5.4. DrawMapRect is multithreaded, but I need to use RectForMapRect here. Can I do it without InvokeOnMainThread?
Error:
MonoTouch.UIKit.UIKitThreadAccessException: UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.
at MonoTouch.UIKit.UIApplication.EnsureUIThread () [0x00019] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:49
at MonoTouch.MapKit.MKOverlayView.RectForMapRect (MKMapRect mapRect) [0x00000] in /Developer/MonoTouch/Source/monotouch/src/MapKit/MKOverlayView.g.cs:146
at MapTest.MyMKOverlayView.DrawMapRect (MKMapRect mapRect, Single zoomScale, MonoTouch.CoreGraphics.CGContext context) [0x00009] in /Users/kirill/Desktop/MapTest/MapTest/MapTestViewController.cs:38
Source code here:
using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.MapKit;
namespace MapTest
{
public class MyMKMapView : MKMapView
{
public MyMKMapView(RectangleF frame) : base(frame)
{
GetViewForOverlay = GetViewForOverlayImp;
}
private MKOverlayView GetViewForOverlayImp(MKMapView mapView, NSObject overlay)
{
return new MyMKOverlayView();
}
public void AddNewOverlay()
{
AddOverlay(new MyMKOverlay());
}
}
public class MyMKOverlayView : MKOverlayView
{
public MyMKOverlayView() : base()
{
}
public override void DrawMapRect(MKMapRect mapRect, float zoomScale, MonoTouch.CoreGraphics.CGContext context)
{
base.DrawMapRect(mapRect, zoomScale, context);
RectForMapRect(new MKMapRect());
}
}
public class MyMKOverlay : MKOverlay
{
public override MKMapRect BoundingMapRect
{
get
{
return new MKMapRect(10 , 10 , 10 , 10);
}
}
public MyMKOverlay() : base()
{
}
}
public partial class MapTestViewController : UIViewController
{
private MyMKMapView _map;
public MapTestViewController() : base ("MapTestViewController", null)
{
_map = new MyMKMapView(View.Bounds);
View.AddSubview(_map);
}
public override void DidReceiveMemoryWarning()
{
// Releases the view if it doesn't have a superview.
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
}
public override void ViewDidUnload()
{
base.ViewDidUnload();
// Clear any references to subviews of the main view in order to
// allow the Garbage Collector to collect them sooner.
//
// e.g. myOutlet.Dispose (); myOutlet = null;
ReleaseDesignerOutlets();
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
_map.AddNewOverlay();
}
public override bool ShouldAutorotateToInterfaceOrientation(UIInterfaceOrientation toInterfaceOrientation)
{
// Return true for supported orientations
return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
}
}
}
Error in line RectForMapRect(new MKMapRect()).
This check is a new feature of MonoTouch 5.4. By default the UI thread check is only enabled on DEBUG builds. You can, at build-time, manually:
disable it (on DEBUG) using --disable-thread-check; or
enable it (on Release) using --force-thread-check;
You can also turn it on/off at runtime using CheckForIllegalCrossThreadCalls.
It's possible that the check is not required, Apple documentation on thread safety is not very clear (unlike MSDN). If you find such case (or simply are not sure) then please fill a bug report.
I have some classes layed out like this
class A
{
public virtual void Render()
{
}
}
class B : A
{
public override void Render()
{
// Prepare the object for rendering
SpecialRender();
// Do some cleanup
}
protected virtual void SpecialRender()
{
}
}
class C : B
{
protected override void SpecialRender()
{
// Do some cool stuff
}
}
Is it possible to prevent the C class from overriding the Render method, without breaking the following code?
A obj = new C();
obj.Render(); // calls B.Render -> c.SpecialRender
You can seal individual methods to prevent them from being overridable:
public sealed override void Render()
{
// Prepare the object for rendering
SpecialRender();
// Do some cleanup
}
Yes, you can use the sealed keyword in the B class's implementation of Render:
class B : A
{
public sealed override void Render()
{
// Prepare the object for rendering
SpecialRender();
// Do some cleanup
}
protected virtual void SpecialRender()
{
}
}
In B, do
protected override sealed void Render() { ... }
try sealed
class B : A
{
protected sealed override void SpecialRender()
{
// do stuff
}
}
class C : B
protected override void SpecialRender()
{
// not valid
}
}
Of course, I think C can get around it by being new.
An other (better ?) way is probablby using the new keyword to prevent a particular virtual method from being overiden:
class A
{
public virtual void Render()
{
}
}
class B : A
{
public override void Render()
{
// Prepare the object for rendering
SpecialRender();
// Do some cleanup
}
protected virtual void SpecialRender()
{
}
}
class B2 : B
{
public new void Render()
{
}
}
class C : B2
{
protected override void SpecialRender()
{
}
//public override void Render() // compiler error
//{
//}
}
yes. If you mark a method as Sealed then it can not be overriden in a derived class.