A few months ago I implemented Design-Mode-Support for our application; the views are WPF & the XAML designer supports design mode for views with a special d:DataContext="{d:DesignInstance vm:MenuViewModel, IsDesignTimeCreatable=True}" attribute so the WPF controls in the XAML preview in Visual Studio are already populated with some sample data to make designing & coding easier. I had to create some rudimentary design mode support for the ViewModel (like constructors without arguments; a little design time DI support) but nothing too tricky.
With the recent MvvmCross update this broke because a Trace extension method failed as a side effect to a property change somewhere deep in the framework; the MvxLog.Instance was null.
I looked for places in the source where MvxLog.Instance is already being initialized and this is during normal application startup (MvxSetup) and in some helper for testing (MvxIocSupportingTest).
So I did the same in my InitializeDesignTimeIoCContainer method but I had to use reflection because the MvxLog class is internal as is the static Instance property. Otherwise it's pretty similar to the code found inside MvvmCross.
[DesignModeOnly] static public void InitializeDesignTimeIoCContainer() { EnforceDesignMode(); var iocProvider = MvxIoCProvider.Initialize(); Mvx.IoCProvider.RegisterSingleton(iocProvider); // Access internal class MvxLog var mvxLogClass = typeof(MvxLogExtensions).Assembly.GetType("MvvmCross.Logging.MvxLog"); var globalLog = new DesignModeLogProvider().GetLogFor(mvxLogClass); // Set static Instance property of MvxLog to globalLog PropertyInfo propInfo = mvxLogClass.GetProperty("Instance", BindingFlags.Static | BindingFlags.NonPublic); propInfo.SetValue(mvxLogClass, globalLog); Mvx.IoCProvider.RegisterSingleton(globalLog); Mvx.IoCProvider.RegisterSingleton<IFMModuleService>(() => new FMModuleServiceMock()); }
Now my design mode support is working again - until the next change...
I understand that this currently isn't a supported scenario so I didn't file this issue as a regression.
Nevertheless here is a real need & my colleagues are enjoying the design time feature so I don't want it to go away.
Some official way to initialize MvxLog.Instance - or better all required internal "properties" - for cases like mine would be very much appreciated.
I'd work on a PR but some guidance would be required.
Beside normal application startup there is already a need when it comes to testing to initialize properties in internal classes like MvxLog.Instance. It would be great if a more general solution would be available, e.g. for design time support as explained above. At least there should be a way to initialize the required classes so that no reflection has to be used.
This sounds kind of what we are doing for our UnitTests: https://github.com/MvvmCross/MvvmCross/blob/develop/MvvmCross.Tests/MvxIoCSupportingTest.cs
GitHub
The .NET MVVM framework for cross-platform solutions, including Xamarin.iOS, Xamarin.Android, Windows and Mac. - MvvmCross/MvvmCross
@Cheesebaron Exactly! (BTW - I mentioned the class in my - pretty long - proposal ;) )
I could imagine some public class that can be used to perform basic initialization - either generally or just for special purposes like design-time support (or testing …).
Some guidance / ideas as how to best integrate this into the large MvvmCross puzzle would be very much appreciated!
A much simpler idea ... One might add lazy initialization to MvxLog.Instance; it might try to get an instance via DI. What do you think of this?
I think this is vote number 2 for making MvxLog not internal. Alternatively as you say we should provide a Design Time helper, which helps setting up all the necessary stuff, similar to what we do in our Tests.
@martijn00, @nickrandolph what do you think?
Any news about this?
Most helpful comment
I think this is vote number 2 for making
MvxLognot internal. Alternatively as you say we should provide a Design Time helper, which helps setting up all the necessary stuff, similar to what we do in our Tests.@martijn00, @nickrandolph what do you think?