2012-08-11 1 views
0

저는 MEF와 함께 일하고 있습니다. 내가 PRISM에서 MVVM RI라고 데모를보고 있었다, 프로그램의 일부가이 코드를 가지고 : 내 소프트웨어에서MEF를 사용하여 가져 오기없이 매개 변수를 생성자에 전달하는 방법은 무엇입니까?

/// <summary> 
    /// Factory class to create a question view model for a given question object. 
    /// </summary> 
    private static class QuestionViewModelFactory 
    { 
     private static Dictionary<Type, Func<Question, QuestionViewModel>> maps = new Dictionary<Type, Func<Question, QuestionViewModel>>() 
     { 
      { typeof(OpenQuestion), (q) => new OpenQuestionViewModel((OpenQuestion)q) }, 
      { typeof(MultipleSelectionQuestion), (q) => new MultipleSelectionQuestionViewModel((MultipleSelectionQuestion)q) }, 
      { typeof(NumericQuestion), (q) => new NumericQuestionViewModel((NumericQuestion)q) } 
     }; 

     public static QuestionViewModel GetViewModelForQuestion(Question question) 
     { 
      Func<Question, QuestionViewModel> viewModelInstanceFactory = null; 
      if (maps.TryGetValue(question.GetType(), out viewModelInstanceFactory)) 
      { 
       return viewModelInstanceFactory(question); 
      } 
      else 
      { 
       throw new ArgumentOutOfRangeException("Could not locate a view model for question type"); 
      } 
     } 
    } 

    // Note that each class derived QuestionViewModel needs a constructor parameter to be created. 
public abstract class QuestionViewModel : NotificationObject 
{ 
    protected QuestionViewModel() { ... } 
} 

public abstract class QuestionViewModel<T> : QuestionViewModel 
    where T : Question 
{ 
    protected QuestionViewModel(T question) { ... } 
} 

을,이 기능이 필요하지만 지금은 발견에 의해 수행하고 싶습니다.

처음에는 QuestionViewModel 만 저장하고 질문 유형 모델 contractName으로 저장하는 사용자 지정 내보내기를 만들려고했습니다. 이것을 확인하십시오.

[MetadataAttribute] 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 
public class ExportViewModelForProblemAttribute : ExportAttribute 
{ 
    public ExportViewModelForProblemAttribute(Type viewModelType, Type questionType) 
     : base(questionType.ToString(), typeof(QuestionViewModel)) 
    { 
    } 
} 

그런데 어떻게 생성자가 객체를 전달할 수 있습니까? 아이디어는 가져 오기를 사용하지 않고 객체 q을 전달하는 것입니다. 그러나 나는이 부분에서 길을 잃었다.

public class ProblemViewModelFactory 
{ 
    private readonly CompositionContainer container; 

    [ImportingConstructor] 
    public ProblemViewModelFactory(CompositionContainer container) 
    { 
     this.container = container; 
    } 

    public QuestionViewModelFactory GetQuestionViewModelFactory(Question question) 
    { 
     // what can I do to return the correspond view model with the question inside? 
    } 
} 

이 매핑을 구현하고 인수를 전달하려면 어떻게해야합니까? 미리 감사드립니다.

답변

0

MEF의 Silverlight 변형에는 ExportFactory<T, TMetadata>이라는 유형을 포함 할 수 있습니다. 이 유형이하는 일은 CreateExport()을 호출 할 때마다 유형의 새로운 인스턴스를 시작하지만 해당 부분에 대한 몇 가지 추가 정보 (메타 데이터)도 포함됩니다.

지금 현재 계약 이름과 같은 질문 이름을 사용하여 질문보기 모델을 내보내는 중입니다. 이렇게하면 모든 QuestionViewModel 유형의 인스턴스를 쉽게 가져올 수 없기 때문에으로 계속 내보내고 유형에 메타 데이터를 추가해야합니다.이 경우 이름 속성이 필요하므로 정의 할 수 있습니다. 우리의 메타 데이터 계약으로 : 이제

public interface INameMetadata 
{ 
    string Name { get; } 
} 

,의 내보내기 속성에 대한 수정 만들어 보자 : 나는 단지 type 인수를 사용하여 기본 생성자를 호출 할 수있는 수출 속성 유형을 변경 한

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 
[MetadataAttribute] 
public class ExportQuestionAttribute : ExportAttribute, INameMetadata 
{ 
    public ExportQuestionAttribute(string name) 
    : base(typeof(QuestionViewModel)) 
    { 
    this.Name = name; 
    } 

    public string Name { get; private set; } 
} 

을하고, 대신 name 값을속성에 저장하십시오.. 실제로 메타 데이터 계약 INameMetadata을 사용하여 내보내기 특성을 꾸밀 필요는 없지만 내보낼 때 필요한 모든 메타 데이터를 제공하고 있는지 확인하는 컴파일 시간을 얻습니다.

다음으로, 우리는 우리의 소비자 유형에 수정을 할 수 있습니다

[Export] 
public class ProblemViewModelFactory 
{ 
    private readonly IEnumerable<ExportFactory<Question, INameMetadata>> _questionFactories; 

    [ImportingConstructor] 
    public ProblemViewModelFactory(
    [ImportMany] IEnumerable<ExportFactory<Question, INameMetadata>> questionFactories) 
    { 
    if (questionFactories == null) 
     throw new ArgumentNullException("questionFactories"); 

    _questionFactories = questionFactories; 
    } 

    public QuestionViewModel GetQuestionViewModel(string name) 
    { 
    return _questionFactories 
     // Get matching question factories 
     .Where(q => q.Metadata.Name == name) 
     // Select the exported value 
     .Select(q => q.CreateExport().Value) 
     // First or default - what if the question doesn't exist? 
     .FirstOrDefault(); 
    } 
} 

지금, 우리는 몇 가지 방법으로이 부분을 수정했습니다.

먼저 부품 공장 컬렉션 인 IEnumerable<ExportFactory<QuestionViewModel, INameMetata>>의 인스턴스 만 허용합니다. 여기에는 수출 된 모든 유형의 질문에 대한 공장이 포함되어야합니다. 가져 오기 부분은 GetQuestionViewModel 메서드입니다 (QuestionViewModelFactory이 아닌 QuestionViewModel을 반환하려고한다고 가정합니다). ExportFactory 형식은 새 인스턴스를 회전하는 작업을 수행하며 형식이 ExportFactory<QuestionViewModel, INameMetadata>이기 때문에 Metadata 속성을 가지며 부분을 만들기 전에 쿼리 할 수있는 INameMetadata 형식의 속성을 갖습니다.

마지막 메서드는 각 INameMetadata 인스턴스의 Name 속성을 확인하고 일치하는 해당 질문을 반환하거나 null을 찾을 수없는 경우 사용 가능한 팩터 집합을 쿼리합니다. 또한 동일한 이름의 여러 질문을 무시하고 첫 번째 질문 만 선택합니다 (이 결정은 귀하에게 달려 있습니다).

올바른 방향으로 안내해 주시기 바랍니다.

+0

답변 주셔서 감사합니다.하지만 QuestionViewModel에 Question 개체 매개 변수가있는 방법을 이해하지 못하고있는 것 같습니다. ExportFactory와 Metadata 태그를 조금 혼란스럽게합니다. –

관련 문제