2015-11-15 22 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}"