Skip to content

Instantly share code, notes, and snippets.

@zirkelc
Created July 2, 2017 14:23
Show Gist options
  • Save zirkelc/cf25c675e6c091dc159d662dc46b5538 to your computer and use it in GitHub Desktop.
Save zirkelc/cf25c675e6c091dc159d662dc46b5538 to your computer and use it in GitHub Desktop.
public static class Instantiator
{
static Dictionary<Type, Func<object>> compiledExpressions = new Dictionary<Type, Func<object>>();
static Dictionary<Tuple<Type, Type>, Func<object>> genericCompiledExpressions = new Dictionary<Tuple<Type, Type>, Func<object>>();
public static T CreateInstance<T>()
{
return (T)CreateInstance(typeof(T));
}
public static object CreateInstance(Type typeDefinition)
{
Func<object> instance;
if (!compiledExpressions.TryGetValue(typeDefinition, out instance))
{
instance = Expression.Lambda<Func<object>>(Expression.New(typeDefinition)).Compile();
compiledExpressions.Add(typeDefinition, instance);
}
return instance();
}
public static object CreateGenericInstance(Type genericTypeDefinition, Type genericParameter)
{
Func<object> instance;
var key = Tuple.Create(genericTypeDefinition, genericParameter);
if (!genericCompiledExpressions.TryGetValue(key, out instance))
{
var genericType = genericTypeDefinition.MakeGenericType(genericParameter);
instance = instance = Expression.Lambda<Func<object>>(Expression.New(genericType)).Compile();
genericCompiledExpressions.Add(key, instance);
}
return instance();
}
}
public class MenuViewModel : ViewModelBase
{
Command navigateCommand;
public Command NavigateCommand => navigateCommand ?? (navigateCommand = new Command(async (navigationKey) => await NavigateAsync((NavigationKeys)navigationKey)));
public Dictionary<NavigationKeys, INavigationItem<ViewModelBase>> NavigationItems { get; } = new Dictionary<NavigationKeys, INavigationItem<ViewModelBase>>();
public MenuViewModel()
{
NavigationItems.Add(NavigationKeys.Feed, new NavigationItem<FeedViewModel>());
NavigationItems.Add(NavigationKeys.Friends, new NavigationItem<FriendsViewModel>());
NavigationItems.Add(NavigationKeys.Groups, new NavigationItem<GroupsViewModel>());
NavigationItems.Add(NavigationKeys.Settings, new NavigationItem<SettingsViewModel>());
}
private async Task NavigateAsync(NavigationKeys navigationKey)
{
var navigationItem = NavigationItems[navigationKey];
if(navigationItem.ViewModel == null)
navigationItem.ViewModel = Instantiator.CreateInstance(navigationItem.ViewModelType) as ViewModelBase;
NavigationService.Instance.SwitchDetailPage(navigationItem.ViewModel);
}
}
public class NavigationService : INavigationService
{
//...
IViewFor<T> InstantiateView<T>(T viewModel) where T : class, IViewModel
{
// Figure out what type the view model is
var viewModelType = viewModel.GetType();
// look up what type of view it corresponds to
var viewType = _viewModelViewDictionary[viewModelType];
// instantiate it
//var view = (IViewFor<T>)Activator.CreateInstance(viewType);
var view = (IViewFor<T>)Instantiator.CreateInstance(viewType);
view.ViewModel = viewModel as T;
return view;
}
IViewFor InstantiateViewForSwitchDetailPage<T>(T viewModel) where T : class, IViewModel
{
var viewModelType = viewModel.GetType();
var viewType = _viewModelViewDictionary[viewModelType];
var view = (IViewFor)Instantiator.CreateInstance(viewType);
var viewModelProperty = viewType.GetRuntimeProperty(nameof(IViewFor<T>.ViewModel));
viewModelProperty?.SetValue(view, viewModel);
return view;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment