2015-11-15 21 views
0

試圖讓我的第一次的MarkupExtension,作爲一個服務定位器,並用它來獲得的DataContext在我的XAML:如何從MarkupExtension返回強類型對象?

視圖模型&接口

public interface IMainViewModel 
{ 
    ICommand OpenProjectCommand { get; } 
} 

public class MainViewModel : IMainViewModel 
{ 
    public ICommand OpenProjectCommand { get; private set; } 
    ... 
} 

服務定位:

public static class ServiceLocator 
{ 
    public static void Map<T>(object concreteType) 
    { 
     // store type 
    } 

    public static T GetInstance<T>() where T : class 
    { 
     // get, instantiate and return 
    } 
} 

應用.xaml

protected override void OnStartup(StartupEventArgs e) 
{ 
    ServiceLocator.Map<IMainViewModel>(typeof(MainViewModel)); 
    base.OnStartup(e); 
} 

的MarkupExtension:

public class ServiceLocatorExtension : MarkupExtension 
{ 
    public Type ServiceType { get; set; } 

    public ServiceLocatorExtension(Type type) 
    { 
     ServiceType = type; 
    } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     if (ServiceType == null) 
      throw new ArgumentException("Type argument is not specified"); 

     var instance = ServiceLocator.GetInstance<IMainViewModel>(); // how to use this.ServiceType? 
     return instance; 
    } 
} 

XAML:

<Window ... DataContext="{loc:ServiceLocator {x:Type loc:IMainViewModel}}"> 
... 
<Button ... Command="{Binding OpenProjectCommand}"/> // problem complains cannot resolve in datacontext type of "object" 

問題:

1)如何我可以使用this.ServiceType財產在的MarkupExtension而不是顯式接口?

2)XAML中的按鈕上的命令綁定抱怨它無法從對象類型的datacontext解析,所以我得到一個警告,我不想。如何讓它知道它的正確類型?

+1

貌似創建非通用'GetInstance(Type type)'方法會讓你的生活更輕鬆,這取決於'GetInstance'的實現方式。在這種情況下,您不需要泛型變體,因爲'ProvideValue'無論如何都會返回'object'。至於第二個問題,如果你得到那個警告,那麼數據上下文不是'MainViewModel'。綁定系統查看對象的實際運行時類型。 –

回答

0

不知道這是否是最好的解決方案,仍然在尋找替代品。

1:

使用反射:

public override object ProvideValue(IServiceProvider serviceProvider) 
{ 
    if (ServiceType == null) 
     throw new ArgumentException("Type argument is not specified"); 

    var serviceLocatorMethod = typeof(ServiceLocator).GetMethod("GetInstance").MakeGenericMethod(ServiceType); 
    return serviceLocatorMethod.Invoke(null, null); 
} 

2:

正如其設計師的問題,這個問題解決了:

d:DataContext="{d:DesignInstance loc:MainViewModel}"